Разделение списка словарей на несколько списков словарей

Я бегаю на это какое-то время безрезультатно... Любая помощь будет очень оценены.

У меня есть:

[{'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 = ...

Ответ 1

используйте defaultdict

import collections

result = collections.defaultdict(list)

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

result_list = result.values()        # Python 2.x
result_list = list(result.values())  # Python 3

Таким образом, вам не нужно делать какие-либо предположения о том, сколько различных событий существует или пропущены какие-либо события.

Это дает вам список списков. Если вы хотите, чтобы индекс dict был проиндексирован по событию, я бы, вероятно, использовал dict(d), если вы планируете использовать произвольный доступ.

Что касается построения группы отдельных списков, я думаю, что это плохая идея. Это потребует создания их в качестве глобалов или использования eval (или хакерства каким-либо другим способом), если вы точно не знаете, сколько их будет, а вы заявляете, что не будете. Лучше всего просто хранить их в контейнере.

Ответ 2

Этот символ O(n log n) из-за сортировки, но я бы не стал слишком беспокоиться, если в списке не было много элементов.

Этот список уже отсортирован по событию, вы можете пропустить тип курса.

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

Ответ 3

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).

Ответ 4

Я думаю, что вы действительно хотите отфильтровать их:

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

это решение не создаст дополнительных структур. (подумайте в случае списка событий HUGE)

Еще одно очень приятное решение - использовать 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}

Ответ 5

На мой взгляд, достаточно простой реализации:

grouping = {}    
for d in dictlist:
    if d[field] not in grouping:
        grouping[d[field]] = []
    grouping[d[field]].append(d)
result = list(result.values())