2010-11-03 134 views
8

我一直在这个短暂的一段时间无法取得任何帮助将大大 赞赏。将词典列表分成几个词典列表

我:

[{'event': 0, 'voltage': 1, 'time': 0}, 
{'event': 0, 'voltage': 2, 'time': 1}, 
{'event': 1, 'voltage': 1, 'time': 2}, 
{'event': 1, 'voltage': 2, 'time': 3}, 
{'event': 2, 'voltage': 1, 'time': 4}, 
{'event': 2, 'voltage': 2, 'time': 5}, 
...] 

,我想分裂词典该列表了每个事件是这样的(可以有任意多的事件):

list0 = [{'event': 0, 'voltage': 1, 'time': 0}, 
{'event': 0, 'voltage': 2, 'time': 1}] 

list1 = [{'event': 1, 'voltage': 1, 'time': 2}, 
{'event': 1, 'voltage': 2, 'time': 3}] 

list2 = [{'event': 2, 'voltage': 1, 'time': 4}, 
{'event': 2, 'voltage': 2, 'time': 5}] 

listN = ... 

回答

10

使用defaultdict

import collections 

result = collections.defaultdict(list) 

for d in dict_list: 
    result[d['event']].append(d) 

result_list = result.values() 

这样,你不必做任何关于有多少不同的假设发生的事件或者是否有任何事件丢失。

这给你一个列表的列表。如果你想要一个按事件索引的dict,如果你打算做任何随机访问,我可能会使用dict(d)

就构建一堆单独的列表而言,我认为这是一个坏主意。它将需要创建它们作为全局变量或使用eval(或以某种其他方式获取hacky),除非您确切知道您将声称不会有多少将会发生。最好把它们放在容器里。

+0

+1我不知道关于defaultdict。谢谢! – dusan 2010-11-03 21:26:11

+0

谢谢,这非常有帮助! – thenickname 2010-11-03 21:53:14

1
dict_list = [{'event': 0, 'voltage': 1, 'time': 0}, 
{'event': 0, 'voltage': 2, 'time': 1}, 
{'event': 1, 'voltage': 1, 'time': 2}, 
{'event': 1, 'voltage': 2, 'time': 3}, 
{'event': 2, 'voltage': 1, 'time': 4}, 
{'event': 2, 'voltage': 2, 'time': 5}, 
] 

import collections 
dol = collections.defaultdict(list) 
for d in dict_list: 
    k = d["event"] 
    dol[k].append(d) 

print dol 

,如果你知道你的“事件”键是连续从零开始的整数,你可以使用一个列表,而不是,但额外的复杂性可能不会得到你任何东西。

defaultdict是在Python 2.5中添加的,但是对于早期版本的解决方法并不难(参见Nick D的代码)。

1

我想你真正想要的是对其进行过滤:

elist = [{'event': 0, 'voltage': 1, 'time': 0}, 
{'event': 0, 'voltage': 2, 'time': 1}, 
{'event': 1, 'voltage': 1, 'time': 2}, 
{'event': 1, 'voltage': 2, 'time': 3}, 
{'event': 2, 'voltage': 1, 'time': 4}, 
{'event': 2, 'voltage': 2, 'time': 5}] 


from itertools import ifilter 

def get_events(elist, n): 
    return ifilter(lambda d: d['event'] == n , elist) 

for e in get_events(elist,0): 
    print e 

该解决方案将不会产生额外的结构。 (想了巨大的事件列表的情况下)

另一个非常不错的解决方案是使用GROUPBY:

from itertools import groupby 
from operator import itemgetter 
for group in groupby(elist, itemgetter('event')): 
    id, event_list = group 
    for e in event_list: 
     print e 

{'time': 0, 'event': 0, 'voltage': 1} 
{'time': 1, 'event': 0, 'voltage': 2} 
{'time': 2, 'event': 1, 'voltage': 1} 
{'time': 3, 'event': 1, 'voltage': 2} 
{'time': 4, 'event': 2, 'voltage': 1} 
{'time': 5, 'event': 2, 'voltage': 2} 
+0

好点,谢谢! – thenickname 2010-11-03 22:06:57

2

这一个是O(n log n)因为那种,但除非有一个我不会太担心lot列表中的项目。

它已经按照事件排序了,你可以跳过这个过程。

>>> from operator import itemgetter 
>>> from itertools import groupby 
>>> d=[{'event': 0, 'voltage': 1, 'time': 0}, 
... {'event': 0, 'voltage': 2, 'time': 1}, 
... {'event': 1, 'voltage': 1, 'time': 2}, 
... {'event': 1, 'voltage': 2, 'time': 3}, 
... {'event': 2, 'voltage': 1, 'time': 4}, 
... {'event': 2, 'voltage': 2, 'time': 5}] 
>>> groupby(sorted(d, key=itemgetter('event')), key=itemgetter('event')) 
<itertools.groupby object at 0xb78138c4> 
>>> for x in _: 
... print x[0], list(x[1]) 
... 
0 [{'time': 0, 'event': 0, 'voltage': 1}, {'time': 1, 'event': 0, 'voltage': 2}] 
1 [{'time': 2, 'event': 1, 'voltage': 1}, {'time': 3, 'event': 1, 'voltage': 2}] 
2 [{'time': 4, 'event': 2, 'voltage': 1}, {'time': 5, 'event': 2, 'voltage': 2}]