python list grouping

python group by key



Lista de grupos por valores (6)

Digamos que tengo una lista como esta:

list = [["A",0], ["B",1], ["C",0], ["D",2], ["E",2]]

¿Cómo puedo agrupar esto más elegantemente para obtener esta salida de lista en Python?

list = [["A", "C"], ["B"], ["D", "E"]]

Entonces los valores se agrupan por el valor seco pero el orden se conserva ...


La respuesta de Howard es concisa y elegante, pero también es O (n ^ 2) en el peor de los casos. Para listas grandes con grandes cantidades de valores clave de agrupación, primero querrá ordenar la lista y luego usar itertools.groupby :

>>> from itertools import groupby >>> from operator import itemgetter >>> seq = [["A",0], ["B",1], ["C",0], ["D",2], ["E",2]] >>> seq.sort(key = itemgetter(1)) >>> groups = groupby(seq, itemgetter(1)) >>> [[item[0] for item in data] for (key, data) in groups] [[''A'', ''C''], [''B''], [''D'', ''E'']]

Editar:

Cambié esto después de ver la respuesta de itemgetter(1) : itemgetter(1) es mejor que lambda x: x[1] .


No sé de elegante, pero ciertamente es factible:

oldlist = [["A",0], ["B",1], ["C",0], ["D",2], ["E",2]] # change into: list = [["A", "C"], ["B"], ["D", "E"]] order=[] dic=dict() for value,key in oldlist: try: dic[key].append(value) except KeyError: order.append(key) dic[key]=[value] newlist=map(dic.get, order) print newlist

Esto conserva el orden de la primera aparición de cada tecla, así como el orden de los elementos para cada tecla. Requiere que la clave sea manejable, pero de otra manera no le asigna ningún significado.


>>> import collections >>> D1 = collections.defaultdict(list) >>> for element in L1: ... D1[element[1]].append(element[0]) ... >>> L2 = D1.values() >>> print L2 [[''A'', ''C''], [''B''], [''D'', ''E'']] >>>


from operator import itemgetter from itertools import groupby lki = [["A",0], ["B",1], ["C",0], ["D",2], ["E",2]] lki.sort(key=itemgetter(1)) glo = [[x for x,y in g] for k,g in groupby(lki,key=itemgetter(1))] print glo

.

EDITAR

Otra solución que no necesita importación, es más legible, mantiene los pedidos y es un 22% menos larga que la anterior:

oldlist = [["A",0], ["B",1], ["C",0], ["D",2], ["E",2]] newlist, dicpos = [],{} for val,k in oldlist: if k in dicpos: newlist[dicpos[k]].extend(val) else: newlist.append([val]) dicpos[k] = len(dicpos) print newlist


len = max(key for (item, key) in list) newlist = [[] for i in range(len+1)] for item,key in list: newlist[key].append(item)

Puedes hacerlo en una sola lista de comprensión, quizás más elegante pero O (n ** 2):

[[item for (item,key) in list if key==i] for i in range(max(key for (item,key) in list)+1)]


values = set(map(lambda x:x[1], list)) newlist = [[y[0] for y in list if y[1]==x] for x in values]