79 votes

Grouper la liste par valeurs

Disons que j'ai une liste comme celle-ci :

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

Comment puis-je regrouper ceci avec le plus d'élégance pour obtenir cette sortie de liste en Python :

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

Donc les valeurs sont regroupées par la valeur secound mais l'ordre est conservé...

105voto

Howard Points 23487
values = set(map(lambda x:x[1], mylist))
newlist = [[y[0] for y in mylist if y[1]==x] for x in values]

43voto

eyquem Points 9942
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

.

MODIFIER

Une autre solution qui ne nécessite aucune importation , est plus lisible, conserve les commandes, et est 22 % plus courte que la précédente :

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

29voto

Robert Rossney Points 43767

La réponse de Howard est concise et élégante, mais c'est aussi O(n^2) dans le pire des cas. Pour les grandes listes avec un grand nombre de valeurs clés de regroupement, vous voudrez d'abord trier la liste, puis utiliser 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']]

Modifier :

J'ai changé cela après avoir vu la réponse de Eyequem : itemgetter(1) est plus agréable que lambda x: x[1].

13voto

DTing Points 12969
>>> 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']]
>>> 

3voto

Yann Vernier Points 3170

Je ne sais pas pour l'élégant, mais c'est certainement faisable :

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

Cela préserve l'ordre de la première occurrence de chaque clé, ainsi que l'ordre des articles pour chaque clé. Il exige que la clé soit hachable, mais ne lui attribue pas autrement de sens.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X