我希望你能解决我目前遇到的问题。我需要构建一个具有以下结构的字典:
iplist={'32': [ '100.107.0.31/32', '100.107.0.3/32' ]
,'24': [ '100.107.0.0/24', '100.107.1.0/24', '100.107.2.0/24' ]
,'22': [ '100.107.0.0/22' ]
,'20': [ '100.107.0.0/20', '100.107.64.0/20' ]
,'16': [ '100.68.0.0/16', '100.69.0.0/16' ]
,'0' : [ '0.0.0.0' ] }
输入数据将是这个,我只需要键:
netlabels={'100.107.0.31/32': 'aa'
,'100.107.0.3/32' : 'bb'
,'100.107.0.0/24' : 'cc'
,'100.107.1.0/24' : 'dd'
,'100.107.2.0/24' : 'ee'
,'100.107.0.0/22' : 'ff'
,'100.107.0.0/20' : 'gg'
,'100.107.64.0/20': 'hh'
,'100.68.0.0/16' : 'hh'
,'100.69.0.0/16' : 'hh'
,'0.0.0.0/0' : 'ii'}
我尝试使用正则表达式和列表理解来完成它,因为将它全部放在一个代码行中真的很酷。我的上一次成功'尝试是这样的:
>>> import re
>>> netlabels={'100.107.0.31/32' : 'aa'
... ,'100.107.0.3/32' : 'bb'
... ,'100.107.0.0/24' : 'cc'
... ,'100.107.1.0/24' : 'dd'
... ,'100.107.2.0/24' : 'ee'
... ,'100.107.0.0/22' : 'ff'
... ,'100.107.0.0/20' : 'gg'
... ,'100.107.64.0/20': 'hh'
... ,'100.68.0.0/16' : 'hh'
... ,'100.69.0.0/16' : 'hh'
... ,'0.0.0.0/0' : 'ii'}
>>>
>>> { re.sub(r'^[^/]+/(\d+)$', r'\1', k) : [k] for k in netlabels.keys() }
{'16': ['100.69.0.0/16'], '24': ['100.107.1.0/24'], '22': ['100.107.0.0/22'], '0': ['0.0.0.0/0'], '20': ['100.107.0.0/20'], '32': ['100.107.0.3/32']}
>>>
但显然列表的值太短了。有许多前缀刚被删除,或者更确切地说,被覆盖。每次需要添加新值时,如何在列表中推送值并附加此列表?
答案 0 :(得分:1)
它真的值得重复:"拥有这一条线就很酷#34;是一个可怕的设计理由。做你想做的事情的方法是使用defaultdict
。另外,我认为你可以不使用正则表达式。
In [5]: data = { '100.107.0.31/32' : 'aa',
...: '100.107.0.3/32' : 'bb',
...: '100.107.0.0/24' : 'cc',
...: '100.107.1.0/24' : 'dd',
...: '100.107.2.0/24' : 'ee',
...: '100.107.0.0/22' : 'ff',
...: '100.107.0.0/20' : 'gg',
...: '100.107.64.0/20' : 'hh',
...: '100.68.0.0/16' : 'hh',
...: '100.69.0.0/16' : 'hh',
...: '0.0.0.0/0' : 'ii'}
In [6]: from collections import defaultdict
In [7]: transformed = defaultdict(list)
In [8]: for key in data:
...: _,_,k = key.rpartition('/')
...: transformed[k].append(key)
...:
结果:
In [10]: transformed
Out[10]:
defaultdict(list,
{'0': ['0.0.0.0/0'],
'16': ['100.68.0.0/16', '100.69.0.0/16'],
'20': ['100.107.0.0/20', '100.107.64.0/20'],
'22': ['100.107.0.0/22'],
'24': ['100.107.0.0/24', '100.107.1.0/24', '100.107.2.0/24'],
'32': ['100.107.0.31/32', '100.107.0.3/32']})
你可以在一条线上实现上述目标,但它可能完全不可读,并且可能不会有任何效率。
defaultdict
的替代方法是使用香草setdefault
的{{1}}方法:
dict
答案 1 :(得分:0)
Juanpa的答案有效,但如果你仍然想使用re
和一行代码,你可以这样做:
>>> import re
>>> netlabels={'100.107.0.31/32' : 'aa'
,'100.107.0.3/32' : 'bb'
,'100.107.0.0/24' : 'cc'
,'100.107.1.0/24' : 'dd'
,'100.107.2.0/24' : 'ee'
,'100.107.0.0/22' : 'ff'
,'100.107.0.0/20' : 'gg'
,'100.107.64.0/20': 'hh'
,'100.68.0.0/16' : 'hh'
,'100.69.0.0/16' : 'hh'}
>>> dct ={}
>>> {dct .setdefault(re.sub(r'^[^/]+/(\d+)$', r'\1', k), []).append(k) for k in netlabels.keys()}
set([None])
>>> dct
{'24': ['100.107.0.0/24', '100.107.1.0/24', '100.107.2.0/24'], '32': ['100.107.0.31/32', '100.107.0.3/32'], '20': ['100.107.0.0/20', '100.107.64.0/20'], '22': ['100.107.0.0/22'], '16': ['100.69.0.0/16', '100.68.0.0/16']}
>>>