2017-02-17 77 views
10

我有一個列表的列表,它看起來像如何獲得特定元素的列表數量?

listOfLists = [ 
    ['a','b','c','d'], 
    ['a','b'], 
    ['a','c'], 
    ['c','c','c','c'] 
] 

我想指望它有一個特定的元素列表的數量。例如,我的輸出應該是

{'a':3,'b':2,'c':3,'d':1} 

正如你所看到的,我不需要一個元素的總數。在"c"的情況下,雖然其總數爲5,但輸出爲3,因爲它僅出現在3個列表中。

我正在使用計數器來計數。下面可以看到同樣的情況。

line_count_tags = [] 
for lists in lists_of_lists: 
    s = set() 
    for element in lists: 
     s.add(t) 
    lines_count_tags.append(list(s)) 

count = Counter([count for counts in lines_count_tags for count in counts]) 

所以,當我打印數量,我得到

{'a':3,'c':3,'b':2,'d':1} 

我想知道如果有一個更好的方式來完成我的目標。

回答

11

使用一個Counter並將每個列表轉換爲一個集合。該set將從每個列表中刪除任何重複,這樣你就不會在同一個列表統計重複值:

>>> from collections import Counter 

>>> Counter(item for lst in listOfLists for item in set(lst)) 
Counter({'a': 3, 'b': 2, 'c': 3, 'd': 1}) 

如果你喜歡函數式編程也可以養活chainset的 - map PED listOfListsCounter

>>> from collections import Counter 
>>> from itertools import chain 

>>> Counter(chain.from_iterable(map(set, listOfLists))) 
Counter({'a': 3, 'b': 2, 'c': 3, 'd': 1}) 

這與第一種方法完全相同(除了可能稍微快一點)。

9

我想每一個列表轉換爲一組在發電機理解計數前傳遞給Counter

import collections 
print(collections.Counter(y for x in listOfLists for y in set(x))) 

結果:

Counter({'a': 3, 'c': 3, 'b': 2, 'd': 1}) 

(這實際上是你做了什麼,但上面的代碼短褲很多循環和臨時列表創建)

7

你可以不用一個Counter,太:

result = {} 
for lis in listOfLists: 
    for element in set(lis): 
     result[element] = result.get(element, 0) + 1 
print result # {'a': 3, 'c': 3, 'b': 2, 'd': 1} 

不是最優雅的,更應該是相當快的。

5

Counter方法與itertools.chain.from_iterable文體差異的一點可能看起來像

Counter(chain.from_iterable(map(set, listOfLists))) 

演示

>>> from itertools import chain 
>>> from collections import Counter 
>>> Counter(chain.from_iterable(map(set, listOfLists))) 
Counter({'a': 3, 'b': 2, 'c': 3, 'd': 1}) 

粗略的基準

%timeit Counter(item for lst in listOfLists for item in set(lst)) 
100000 loops, best of 3: 13.5 µs per loop 

%timeit Counter(chain.from_iterable(map(set, listOfLists))) 
100000 loops, best of 3: 12.4 µs per loop 
+0

我在CPython 2.7.11上使用'itertools.chain'(〜40%!)獲得更快的執行速度。儘管如此,'Counter' +'itertools.chain'的執行速度比我提出的'raw'方法慢4倍。 – zwer

+1

@zwer Eh,取決於我們正在討論的輸入大小。我的解決方案有更多的開銷,但如果您增加輸入大小,它應該更快。這就是爲什麼基準測試不是太重要:) – miradulo

+0

的確如此,我只是對我的位置在速度方面的巨大差異感到驚訝,我不習慣「itertools」實際上表現超越,幾乎任何東西 - 它們都是通常是較慢的,但更易於閱讀的選擇:D – zwer

3

只需轉換爲set,使用itertools.chain.from_iterable展平,然後輸入Counter即可。

from collections import Counter 
from itertools import chain 

inp = [ 
    ['a','b','c','d'], 
    ['a','b'], 
    ['a','c'], 
    ['c','c','c','c'] 
] 


print(Counter(chain.from_iterable(map(set, inp)))) 
2

這種方法使用一套理解計算獨特的條目listOfLists,然後使用字典解析

A = {val for s in listOfLists for val in s} 
d = {i: sum(i in j for j in listOfLists) for i in A} 
print(d) # {'a': 3, 'c': 3, 'b': 2, 'd': 1} 

我承認這是一個有點難看計算每單出現,但它是一個可能的解決方案(和字典理解的一個很酷的使用)。 您還可以通過移動A計算對入字典解析

+0

不需要再次將您的集合'A'轉換爲列表或者以列表理解的形式提供集合,生成表達式更好......實際上您可以構建'A '也作爲一種理解 – Copperfield

+0

@Copperfield感謝您的建議。我做了一個改變。 – nbryans

2

這裏做這一個班輪是使用循環另一個版本:

listOfLists = [ 
    ['a','b','c','d'], 
    ['a','b'], 
    ['a','c'], 
    ['c','c','c','c'] 
    ] 

final = {} 
for lst in listOfLists: 
    for letter in lst: 
     if letter in final: 
      final[letter] += 1 
     else: 
      final[letter] = 1 

所以創建一個名爲最後一個空的字典。然後遍歷每個列表的每個字母。如果該字母在最終還不存在作爲關鍵字,則創建一個新的關鍵字和值= 1。否則,加1到該鍵的值。

相關問題