如何将列表中的相同值分组到自己的列表中?

Oam*_*nji 4 python list-comprehension

说我有一个清单 [2, 3, 7, 2, 3, 8, 7, 3]

我想生成包含上面列表中相同值的列表.

预期输出类似于:

[2, 2]
[3, 3, 3]
[7, 7]
[8]
Run Code Online (Sandbox Code Playgroud)

生成这些列表的顺序无关紧要.

Net*_*ave 5

最好的方法是使用以下O(n)解决方案collections.defaultdict

>>> l = [2, 3, 7, 2, 3, 8, 7, 3]
>>> d = defaultdict(list)
>>> for e in l:
...     d[e].append(e)
... 
>>> d
defaultdict(<class 'list'>, {2: [2, 2], 3: [3, 3, 3], 7: [7, 7], 8: [8]})
>>> d.values()
dict_values([[2, 2], [3, 3, 3], [7, 7], [8]])
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用已itertools.groupby排序列表:

>>> for _, l in itertools.groupby(sorted(l)):
...     print(list(l))
... 
[2, 2]
[3, 3, 3]
[7, 7]
[8]
Run Code Online (Sandbox Code Playgroud)

或列表理解collections.Counter

>>> from collections import Counter
>>> [[i]*n for i,n in Counter(l).items()]
[[2, 2], [3, 3, 3], [7, 7], [8]]
Run Code Online (Sandbox Code Playgroud)

如我O(n)所言,defaultdict解决方案比其他方法更快。测试如下:

from timeit import timeit


setup = (
"from collections import Counter, defaultdict;"
"from itertools import groupby;"
"l = [2, 3, 7, 2, 3, 8, 7, 3];"
)

defaultdict_call = (
"d = defaultdict(list); "
"\nfor e in l: d[e].append(e);"
)
groupby_call = "[list(g) for _,g in groupby(sorted(l))]"
counter_call = "[[i]*n for i,n in Counter(l).items()]"


for call in (defaultdict_call, groupby_call, counter_call):
  print(call)
  print(timeit(call, setup))
Run Code Online (Sandbox Code Playgroud)

结果:

d = defaultdict(list); 
for e in l: d[e].append(e);
7.02662614302244
[list(g) for _,g in groupby(sorted(l))]
10.126392606005538
[[i]*n for i,n in Counter(l).items()]
19.55539561196929
Run Code Online (Sandbox Code Playgroud)

这是现场测试