使用特定规则在列表上迭代

2024-04-19 08:19:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一个分析DHCP数据包的程序,遇到了选项43(特定于供应商的信息)。这更多的是一个编程问题,在技术上与网络和DHCP关系不大,因此我将其标记为python。你知道吗

根据RFC 2132(第19页),方案43的结构如下:

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

当转换为python“bytes”对象时,它应该如下所示:

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

其中n是数据项的长度(Dn)。你知道吗

理想情况下,我希望迭代这个bytes对象,并将每个数据项的代码保存为键,并将其映射到适当的数据项值。即:

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

例如:

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

应该转化为:

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

在python中有正确的方法吗?你知道吗

编辑:也是。代码(Tn)是唯一的。你知道吗


Tags: 对象代码datalenbytescodeitemdhcp
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不应重复。你知道吗

使用递归函数:

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]}

还可以将for循环与itertor结合使用。外部for循环将遍历T的所有值,而对循环内next的调用将从列表中删除nd1,…,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

你甚至可以把这些都放到一本字典里。。。你知道吗

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

示例:

>>> 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]}

相关问题 更多 >