按值分组列表

89 投票
9 回答
237740 浏览
提问于 2025-04-16 15:55

假设我有这样一个列表:

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

我怎么才能优雅地把它分组,得到这个列表输出呢:

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

这里的值是根据第二个值来分组的,但顺序是保持不变的……

9 个回答

31

霍华德的回答简洁明了,但在最坏的情况下,它的效率是O(n^2)。对于那些包含很多分组键值的大列表,建议先对列表进行排序,然后再使用 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']]

补充:

我在看到eyequem的回答后做了修改: itemgetter(1)lambda x: x[1] 更好用。

45
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

.

编辑

还有一种解决方案,不需要导入,读起来更清晰,保持了顺序,而且比之前的方案短了22%:

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
118
values = set(map(lambda x:x[1], mylist))
newlist = [[y[0] for y in mylist if y[1]==x] for x in values]

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。

撰写回答