Iterate over a list with defined rules

I am writing a program that analyzes DHCP packets and came across option 43 (Vendor Specification). This is more of a programming issue and less technically related to network and DHCP, so I marked it as just python.

According to RFC 2132 (p. 19), the structure of option 43 is as follows:

 Code   Len   Data item        Code   Len   Data item       Code
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|  T1 |  n  |  d1 |  d2 | ... |  T2 |  n  |  D1 |  D2 | ... | ... |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+

When moving to a python byte object, it should look something like this:

[T1, n, d1, d2, ..., T2, n, D1, D2, ...]

Where n is the length of the data element (Dn).

Ideally, I want to iterate over this byte object and save the code for each data item as a key and map it to the corresponding data item value. IE:

{T1: [d1, d2, d3], T2: [D1, D2, D3]}

For instance:

[0, 1, 2, 1, 2, 5, 6, 3, 4, 9, 10, 11, 12]

Should translate to this:

{0: [2], 1: [5,6], 3: [9, 10, 11, 12]}

Is there a proper way to do this in python?

EDIT: Yes, yes. Codes (Tn) are unique.

+4
4

:

trans_dict = {}
def translate(lst, trans_dict):
    if(len(lst) == 0):
        return
    else:   ​
        trans_dict[lst[0]] = lst[2:(2+lst[1])]        # the first element will be the key, 
                                                      # the value starts from the third 
                                                      # element with length of the second element
        translate(lst[(2+lst[1]):], trans_dict)

translate(lst, trans_dict)

trans_dict
# {0: [2], 1: [5, 6], 3: [9, 10, 11, 12]}
+3

:

packets = [0, 1, 2, 1, 2, 5, 6, 3, 4, 9, 10, 11, 12]

pos_head = 0
len_data = len(packets)

d = dict()

while pos_head  < len_data:
    key = packets[pos_head]
    if pos_head +2 > len_data:
        break
    size = packets[pos_head+1]
    if pos_head + 2 + size > len_data:
        break
    data = packets[pos_head+2: pos_head+2 + size]
    pos_head += 2 + size
    d[key] = data

print(d)

:

{0: [2], 1: [5, 6], 3: [9, 10, 11, 12]}

: T1, T2,..., Tn .

+2

You can also use a loop forin combination with itertor. The outer loop forwill iterate over all the values T, and the calls nextin the loop will remove from the list nand d1, ..., dn.

def parse(data):
    iterator = iter(data)
    d = {}
    for t in iterator:
        n = next(iterator)
        d[t] = [next(iterator) for _ in range(n)]
    return d

You could put all this in one understanding of the dictionary ...

def parse(data):
    it = iter(data)
    return {t: [next(it) for _ in range(next(it))] for t in it}

Example:

>>> data = [0, 1, 2, 1, 2, 5, 6, 3, 4, 9, 10, 11, 12]
>>> parse(data)
{0: [2], 1: [5, 6], 3: [9, 10, 11, 12]}
+2
source

Using nested loops whileand for, my solution ( T1to Tnshould be unique, as they are cast keys of the dictionary):

my_list = [0, 1, 2, 1, 2, 5, 6, 3, 4, 9, 10, 11, 12]

res = {}
i = 0

while i < len(my_list):
    num = my_list[i+1]
    for j in range(i+2, i+2+num):
        if i in res:
            res[i].append(my_list[j])
        else:
            res[i] = [my_list[j]]
    i += 2 + num

Conclusion:

>>> res
{0: [2], 3: [5, 6], 7: [9, 10, 11, 12]}
+1
source

Source: https://habr.com/ru/post/1665011/


All Articles