按值列出组列表

Vel*_*les 54 python grouping list

假设我有一个这样的列表:

list = [["A",0], ["B",1], ["C",0], ["D",2], ["E",2]]
Run Code Online (Sandbox Code Playgroud)

我怎样才能最优雅地将其分组以在Python中获取此列表输出:

list = [["A", "C"], ["B"], ["D", "E"]]
Run Code Online (Sandbox Code Playgroud)

所以这些值按secound值分组但订单仍然保留......

How*_*ard 83

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

  • 该分组可以简单地在“O(n)”中完成,但在这段代码中,如果“mylist”中的元素全部不同,则将花费“O(n ^ 2)”。 (5认同)
  • `set()` 不一定是排序的(尽管它适用于小整数值),如果您的范围很长,请使用 `values = Sorted(set(...`) (2认同)
  • @sverre毕竟不需要排序 (2认同)
  • 除了'set`没有订单.恰好,对于低整数,哈希函数是身份.我也不确定OP是否打算同时订购(团体订单和团体订单); 这个和sverre的例子按键排序组(他也假设0..N连续范围). (2认同)
  • `lambda x:x [1]`可以用[`operator.itemgetter(1)`](https://docs.python.org/library/operator.html#operator.itemgetter)替换. (2认同)

eyq*_*uem 29

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
Run Code Online (Sandbox Code Playgroud)

.

编辑

另一个不需要导入的解决方案,更具可读性,保留订单,并且比前一个解决方案长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
Run Code Online (Sandbox Code Playgroud)

  • 使用`itemgetter`的+1.但请注意,既然你在迭代`groupby`返回的迭代器,你就不需要`list(g)`. (2认同)
  • @Robert Rossney Eagle的眼睛.+1.顺便说一句,在你的代码中,我发现"数据"这个词太常见了,不知道它是什么类型的数据,这很可惜. (2认同)

Rob*_*ney 22

霍华德的答案简洁而优雅,但在最坏的情况下也是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']]
Run Code Online (Sandbox Code Playgroud)

编辑:

看到eyequem的答案之后,我改变了这个: itemgetter(1)比...更好lambda x: x[1].

  • 我也这么认为.此外,提醒`operator`模块的存在总是好的. (4认同)
  • 但它需要导入.它真的比使用lambda更好吗?我想知道.无论如何,为了便于阅读,我认为itemgetter更好 (2认同)
  • 我更喜欢lambda。 (2认同)

DTi*_*ing 7

>>> 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']]
>>> 
Run Code Online (Sandbox Code Playgroud)