我正在尝试将字典列表按两个键/值分成多个列表。字典的原始列表是从返回数据速度较慢的应用程序(第3方)中提取的,因此我避免了多次调用,现在可以在一个查询中获取所需的所有数据。但是,我现在需要将这些数据分成与NodeID和名称匹配的组,同时保持原始数据
样本数据:
[{'NodeID': 1563, 'Name': 'GigabitEthernet1/1/1', 'InAveragebps': 0.03555526, 'OutAveragebps': 64.50593, 'DateTime': '2018-05-29T01:10:00.0000000'
},
{'NodeID': 1563, 'Name': 'GigabitEthernet1/1/1', 'InAveragebps': 0.04555526, 'OutAveragebps': 6456.50593, 'DateTime': '2018-05-29T01:11:00.0000000'
},
{'NodeID': 1788, 'Name': 'GigabitEthernet2/1/2', 'InAveragebps': 0.03554479, 'OutAveragebps': 64.7012558, 'DateTime': '2018-05-16T01:01:00.0000000'
},
{'NodeID': 1788, 'Name': 'GigabitEthernet2/1/2', 'InAveragebps': 0.03555063, 'OutAveragebps': 64.62538, 'DateTime': '2018-05-17T01:011:00.0000000'
}]
所以看跌期权将有两个清单:
[{'NodeID': 1563, 'Name': 'GigabitEthernet1/1/1', 'InAveragebps': 0.03555526, 'OutAveragebps': 64.50593, 'DateTime': '2018-05-29T01:10:00.0000000'
},
{'NodeID': 1563, 'Name': 'GigabitEthernet1/1/1', 'InAveragebps': 0.04555526, 'OutAveragebps': 6456.50593, 'DateTime': '2018-05-29T01:11:00.0000000'
}],[
{'NodeID': 1788, 'Name': 'GigabitEthernet2/1/2', 'InAveragebps': 0.03554479, 'OutAveragebps': 64.7012558, 'DateTime': '2018-05-16T01:01:00.0000000'
},
{'NodeID': 1788, 'Name': 'GigabitEthernet2/1/2', 'InAveragebps': 0.03555063, 'OutAveragebps': 64.62538, 'DateTime': '2018-05-17T01:011:00.0000000'
}]
我尝试使用itertools,集合:
from operator import itemgetter
from itertools import groupby
interface_data = []
grouper = itemgetter("NodeID", "Name")
for key,v in groupby(sorted(results, key = grouper), grouper):
temp_dict = dict(zip(["NodeID", "Name"], key))
interface_data.append(temp_dict)
收藏
from collections import defaultdict
interface_data = defaultdict(list)
for i in results:
interface_data[(i['NodeID'],i['InterfaceName'])].append(i)
考虑到这看起来多么简单,我现在什么都没得到,这令人沮丧。
答案 0 :(得分:4)
您可以使用defaultdict
创建一个嵌套字典,然后对其值调用list()
:
>>> from collections import defaultdict
>>> interface_data = defaultdict(list)
>>> for i in s:
... key = i['NodeID'], i['Name']
... interface_data[key].append(i)
>>> list(interface_data.values())
[[{'NodeID': 1563,
'Name': 'GigabitEthernet1/1/1',
'InAveragebps': 0.03555526,
'OutAveragebps': 64.50593,
'DateTime': '2018-05-29T01:10:00.0000000'},
{'NodeID': 1563,
'Name': 'GigabitEthernet1/1/1',
'InAveragebps': 0.04555526,
'OutAveragebps': 6456.50593,
'DateTime': '2018-05-29T01:11:00.0000000'}],
[{'NodeID': 1788,
'Name': 'GigabitEthernet2/1/2',
'InAveragebps': 0.03554479,
'OutAveragebps': 64.7012558,
'DateTime': '2018-05-16T01:01:00.0000000'},
{'NodeID': 1788,
'Name': 'GigabitEthernet2/1/2',
'InAveragebps': 0.03555063,
'OutAveragebps': 64.62538,
'DateTime': '2018-05-17T01:011:00.0000000'}]]
返回列表结果可能有点round回,但是最终您想要进行某种类型的成员资格测试(或者,在这种情况下,更像是查找),并且字典很适合-首先适合它。
在调用list()
之前,interface_data
是一个嵌套字典;它的键是2个元组(节点ID,名称),其值是字典本身。
>>> interface_data.keys()
dict_keys([(1563, 'GigabitEthernet1/1/1'), (1788, 'GigabitEthernet2/1/2')])
答案 1 :(得分:1)
对于这个问题,itertools.groupby
非常简单,因为只有'NodeId'
被用作分组密钥:
import itertools
d = [{'NodeID': 1563, 'Name': 'GigabitEthernet1/1/1', 'InAveragebps': 0.03555526, 'OutAveragebps': 64.50593, 'DateTime': '2018-05-29T01:10:00.0000000'}, {'NodeID': 1563, 'Name': 'GigabitEthernet1/1/1', 'InAveragebps': 0.04555526, 'OutAveragebps': 6456.50593, 'DateTime': '2018-05-29T01:11:00.0000000'}, {'NodeID': 1788, 'Name': 'GigabitEthernet2/1/2', 'InAveragebps': 0.03554479, 'OutAveragebps': 64.7012558, 'DateTime': '2018-05-16T01:01:00.0000000'}, {'NodeID': 1788, 'Name': 'GigabitEthernet2/1/2', 'InAveragebps': 0.03555063, 'OutAveragebps': 64.62538, 'DateTime': '2018-05-17T01:011:00.0000000'}]
final_result = [list(b) for _, b in itertools.groupby(d, key=lambda x:x['NodeID'])]
输出:
[[{'NodeID': 1563, 'Name': 'GigabitEthernet1/1/1', 'InAveragebps': 0.03555526, 'OutAveragebps': 64.50593, 'DateTime': '2018-05-29T01:10:00.0000000'}, {'NodeID': 1563, 'Name': 'GigabitEthernet1/1/1', 'InAveragebps': 0.04555526, 'OutAveragebps': 6456.50593, 'DateTime': '2018-05-29T01:11:00.0000000'}], [{'NodeID': 1788, 'Name': 'GigabitEthernet2/1/2', 'InAveragebps': 0.03554479, 'OutAveragebps': 64.7012558, 'DateTime': '2018-05-16T01:01:00.0000000'}, {'NodeID': 1788, 'Name': 'GigabitEthernet2/1/2', 'InAveragebps': 0.03555063, 'OutAveragebps': 64.62538, 'DateTime': '2018-05-17T01:011:00.0000000'}]]
编辑:
如果不能保证您的数据按id
进行排序,则必须应用sorted
:
final_result = [list(b) for _, b in itertools.groupby(sorted(d, key=lambda x:x['NodeID']), key=lambda x:x['NodeID'])]
答案 2 :(得分:0)
您使用itertools.groupby
的解决方案已经非常接近,但是除了附加key
之外,您还应该在将v
转换为列表后附加from operator import itemgetter
from itertools import groupby
interface_data = []
grouper = itemgetter("NodeID", "Name")
for _, v in groupby(sorted(results, key = grouper), grouper):
interface_data.append(list(v))
print(interface_data)
:
[[{'NodeID': 1563, 'Name': 'GigabitEthernet1/1/1', 'InAveragebps': 0.03555526, 'OutAveragebps': 64.50593, 'DateTime': '2018-05-29T01:10:00.0000000'}, {'NodeID': 1563, 'Name': 'GigabitEthernet1/1/1', 'InAveragebps': 0.04555526, 'OutAveragebps': 6456.50593, 'DateTime': '2018-05-29T01:11:00.0000000'}], [{'NodeID': 1788, 'Name': 'GigabitEthernet2/1/2', 'InAveragebps': 0.03554479, 'OutAveragebps': 64.7012558, 'DateTime': '2018-05-16T01:01:00.0000000'}, {'NodeID': 1788, 'Name': 'GigabitEthernet2/1/2', 'InAveragebps': 0.03555063, 'OutAveragebps': 64.62538, 'DateTime': '2018-05-17T01:011:00.0000000'}]]
这将输出:
input=|3E 00|redcar|0D|.