Resumir una lista de diccionarios basados ​​en valores clave comunes

Tengo una lista de diccionarios así:

dictlist = [{'day': 0, 'start': '8:00am', 'end': '5:00pm'}, {'day': 1, 'start': '10:00am', 'end': '7:00pm'}, {'day': 2, 'start': '8:00am', 'end': '5:00pm'}, {'day': 3, 'start': '10:00am', 'end': '7:00pm'}, {'day': 4, 'start': '8:00am', 'end': '5:00pm'}, {'day': 5, 'start': '11:00am', 'end': '1:00pm'}] 

Quiero resumir los días que comparten los mismos tiempos de 'start' y 'end' .

Por ejemplo,

 summarylist = [([0,2, 4], '8:00am', '5:00pm'), ([1, 3], '10:00am', '7:00pm') ([5], '11:00am', '1:00pm')] 

He intentado adaptar algunas otras soluciones de StackOverflow en relación con los conjuntos e intersecciones para lograr esto sin suerte. Estaba intentando reutilizar la solución a esta pregunta en vano. Espero que alguien pueda apuntarme en la dirección correcta.

Si no necesita el formato exacto que proporciona, puede usar defaultdict

 dictlist = [{'day': 0, 'start': '8:00am', 'end': '5:00pm'}, {'day': 1, 'start': '10:00am', 'end': '7:00pm'}, {'day': 2, 'start': '8:00am', 'end': '5:00pm'}, {'day': 3, 'start': '10:00am', 'end': '7:00pm'}, {'day': 4, 'start': '8:00am', 'end': '5:00pm'}, {'day': 5, 'start': '11:00am', 'end': '1:00pm'}] from collections import defaultdict dd = defaultdict(list) for d in dictlist: dd[(d['start'],d['end'])].append(d['day']) 

Resultado:

 >>> dd defaultdict(, {('11:00am', '1:00pm'): [5], ('10:00am', '7:00pm'): [1, 3], ('8:00am', '5:00pm'): [0, 2, 4]}) 

Y si el formato es importante para usted podría hacer:

 >>> my_list = [(v, k[0], k[1]) for k,v in dd.iteritems()] >>> my_list [([5], '11:00am', '1:00pm'), ([1, 3], '10:00am', '7:00pm'), ([0, 2, 4], '8:00am', '5:00pm')] >>> # If you need the output sorted: >>> sorted_my_list = sorted(my_list, key = lambda k : len(k[0]), reverse=True) >>> sorted_my_list [([0, 2, 4], '8:00am', '5:00pm'), ([1, 3], '10:00am', '7:00pm'), ([5], '11:00am', '1:00pm')] 

Con itertools.groupby :

 In [1]: %paste dictlist = [{'day': 0, 'start': '8:00am', 'end': '5:00pm'}, {'day': 1, 'start': '10:00am', 'end': '7:00pm'}, {'day': 2, 'start': '8:00am', 'end': '5:00pm'}, {'day': 3, 'start': '10:00am', 'end': '7:00pm'}, {'day': 4, 'start': '8:00am', 'end': '5:00pm'}, {'day': 5, 'start': '11:00am', 'end': '1:00pm'}] ## -- End pasted text -- In [2]: from itertools import groupby In [3]: tuplist = [(d['day'], (d['start'], d['end'])) for d in dictlist] In [4]: key = lambda x: x[1] In [5]: summarylist = [(sorted(e[0] for e in g),) + k ...: for k, g in groupby(sorted(tuplist, key=key), key=key)] In [6]: summarylist Out[6]: [([1, 3], '10:00am', '7:00pm'), ([5], '11:00am', '1:00pm'), ([0, 2, 4], '8:00am', '5:00pm')] 

Puedes usar itertools.groupby esta manera.

código fuente:

 from itertools import groupby for k, grp in groupby(sorted(dictlist, key=lambda x:(x['end'], x['start'])), key=lambda x:(x['start'], x['end'])): print [i['day'] for i in grp], k 

salida:

 [5] ('11:00am', '1:00pm') [0, 2, 4] ('8:00am', '5:00pm') [1, 3] ('10:00am', '7:00pm') 

Pero creo que usar defaultdict (respuesta @Akavall) es la forma correcta en este caso particular.