2010-11-03 12 views
8

He estado golpeando en esto por un tiempo en vano ... Cualquier ayuda sería en gran medida apreciada.División de una lista de diccionarios en varias listas de diccionarios

que tengo:

[{'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}, 
...] 

y quiero dividir esa lista de diccionarios hasta por evento como este (no puede ser arbitrariamente muchos eventos):

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

Respuesta

10

uso defaultdict

import collections 

result = collections.defaultdict(list) 

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

result_list = result.values() 

De esta manera, no tiene que hacer suposiciones sobre cuántos diferentes eventos que hay o si faltan eventos.

Esto le da una lista de listas. Si desea un dict indexado por evento, probablemente usaría dict(d) si planea hacer algún acceso aleatorio.

En cuanto a la construcción de un montón de listas individuales, creo que esa es una mala idea. Necesitará crearlos como globales o usar eval (o hacerse hacky de alguna otra manera) a menos que sepa exactamente cuántos va a haber y no lo hará. Lo mejor es mantenerlos en un contenedor.

+0

+1 No sabía acerca de defaultdict. ¡Gracias! – dusan

+0

¡Gracias, eso fue muy útil! – thenickname

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 

si sabe que sus teclas de "eventos" son números enteros de base cero consecutivos, se puede utilizar una lista en lugar, pero la complejidad extra no se puede ganar nada.

defaultdict se agregó en python 2.5, pero la solución para las versiones anteriores no es difícil (vea el código de Nick D).

1

creo que lo que realmente quiere es filtrar ellas:

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 

esta solución no va a crear estructuras adicionales. (Que en el caso de la lista de eventos enorme)

Otra solución es muy agradable de usar 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

¡Buen punto, gracias! – thenickname

2

Ésta es O(n log n) a causa de la especie, pero no me preocupa demasiado a menos que haya una lote de elementos en la lista.

Si la lista ya está ordenada por evento, puede omitir el tipo de curso.

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