Разделение списка словарей на несколько списков словарей - PullRequest
14 голосов
/ 04 ноября 2010

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

У меня есть:

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

Ответы [ 4 ]

16 голосов
/ 04 ноября 2010

использование 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 (или каким-то другим образом стать хакером), если вы точно не знаете, сколько их будет, а вы заявляете, что не будете. Лучше всего хранить их в контейнере.

4 голосов
/ 04 ноября 2010

Это 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}]
1 голос
/ 04 ноября 2010

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

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}
1 голос
/ 04 ноября 2010
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 был добавлен в python2.5, но обходной путь для более ранних версий не сложен (см. Код Ника Д.).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...