说我有一个列表[2, 3, 7, 2, 3, 8, 7, 3]
我想产生包含与上面列表相同值的列表。
预期输出类似:
[2, 2]
[3, 3, 3]
[7, 7]
[8]
这些列表的生成顺序无关紧要。
答案 0 :(得分:5)
最好的方法是使用collections.defaultdict
的O(n)
解决方案:
>>> 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]])
或者,您可以将itertools.groupby
与排序列表一起使用:
>>> for _, l in itertools.groupby(sorted(l)):
... print(list(l))
...
[2, 2]
[3, 3, 3]
[7, 7]
[8]
或使用collections.Counter
进行列表理解:
>>> from collections import Counter
>>> [[i]*n for i,n in Counter(l).items()]
[[2, 2], [3, 3, 3], [7, 7], [8]]
正如我所张贴的那样,defaultdict解决方案是O(n)
,并且比其他方法更快。这是测试:
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))
结果:
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
这里是live test
答案 1 :(得分:4)
尝试一下
l = [2, 3, 7, 2, 3, 8, 7, 3]
for i in set(l):
print([i]*l.count(i))
输出:
[8]
[2, 2]
[3, 3, 3]
[7, 7]
答案 2 :(得分:3)
这是使用Counter
from collections import Counter
my_dict = Counter([2, 3, 7, 2, 3, 8, 7, 3]) # returns {3: 3, 2: 2, 7: 2, 8: 1}
new_list = [[k] * v for k,v in my_dict.items()]
输出:
[[2, 2], [3, 3, 3], [7, 7], [8]]
答案 3 :(得分:3)
一种方法是使用简单的dictionary:
l = [2, 3, 7, 2, 3, 8, 7, 3]
groups = {}
for n in l:
groups.setdefault(n, []).append(n)
print(list(groups.values()))
# [[2, 2], [3, 3, 3], [7, 7], [8]]
答案 4 :(得分:2)
在Numpy数组中执行此操作会很有效
a= np.array([2, 3, 7, 2, 3, 8, 7, 3])
[a[a==i] for i in np.unique(a)]
输出:
[array([2, 2]), array([3, 3, 3]), array([7, 7]), array([8])]
答案 5 :(得分:2)
我认为您可以尝试使用collections.Counter,并在此列表中获得不同的键及其计数。
from collections import Counter
l = [2, 3, 7, 2, 3, 8, 7, 3]
c =Counter(l)
print(c) ## result: {3: 3, 2: 2, 7: 2, 8: 1}
答案 6 :(得分:2)
此答案与 列表理解 :
l = [2, 3, 7, 2, 3, 8, 7, 3]
print(*[[i]*l.count(i) for i in set(l)], sep='\n')
输出:
C:\Users\Desktop>py x.py
[8]
[2, 2]
[3, 3, 3]
[7, 7]
此外,使用sorted()
方法可以完全按照您的要求进行输出
l = [2, 3, 7, 2, 3, 8, 7, 3]
print(*sorted([[i]*l.count(i) for i in set(l)]), sep='\n')
输出:
C:\Users\Desktop>py x.py
[2, 2]
[3, 3, 3]
[7, 7]
[8]
编辑::随着答案的增加,我想详细解释代码,以尽我所能。
代码是这样的:
print(*[[i]*l.count(i) for i in set(l)], sep='\n')
使用set(l)
将消除重复的值,并且仅将[2, 3, 7, 8]
保留在列表中。稍后,在[i]
中,将set(l)
的每个元素放入新列表中。我们计算i
元素(i
是set(l
中的元素)在本机列表l
(l = [2, 3, 7, 2, 3, 8, 7, 3]
)中出现了多少次。并且在[i]*l.count(i)
i
中成为新列表中的l.count(i)
次。列表理解方法在迭代完成后获取所有值,并将其打包在列表中并返回列表。开头的*
符号用于解压缩返回列表中的值。最后,*print()*
关键字sep='\n'
在解压缩列表中的每个元素之后放置一个'\n'
。没有它,它可以像这样完成:
for j in [[i]*l.count(i) for i in set(l)]:
print(j)