[英]How to group identical values from a list into their own lists?
說我有一個清單[2, 3, 7, 2, 3, 8, 7, 3]
2,3,7,2,3,8,7,3 [2, 3, 7, 2, 3, 8, 7, 3]
我想生成包含上面列表中相同值的列表。
預期輸出類似於:
[2, 2]
[3, 3, 3]
[7, 7]
[8]
生成這些列表的順序無關緊要。
最好的方法是使用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)
並且比其他aproaches更快。 以下是測試:
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
這是現場測試
嘗試這個
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]
這是使用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]]
一種方法是使用簡單的字典 :
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]]
在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])]
我想你可以試試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}
這個答案是列表理解 :
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')
OUTPUT:
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)
次。 List-comprehension方法在迭代完成后獲取所有值,並將其打包在列表中並返回列表。 *
開頭的標志用於解壓縮返回列表中的值。 最后*print()*
keyword sep='\\n'
在解壓縮列表中的每個元素后放一個'\\n'
。 如果沒有它,可以這樣做:
for j in [[i]*l.count(i) for i in set(l)]:
print(j)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.