[英]Most frequent values in a dictionary
我有以下字典:
d = {"a":["MRS","VAL"],"b":"PRS","c":"MRS","d":"NTS"}
我想創建一個字典,給出每個值的出現。 基本上,它看起來像:
output = {"MRS":2,"PRS":1,"NTS":1,"VAL":1}
有誰知道我該怎么做? 提前致謝 !
由於您的字典由字符串和字符串列表組成,因此您首先需要將這些元素展平為常見的字符串類型:
import collections
d = {"a":["MRS","VAL"],"b":"PRS","c":"MRS","d":"NTS"}
def flatten(l):
for el in l:
if isinstance(el, collections.Iterable) and not isinstance(el, basestring):
for sub in flatten(el):
yield sub
else:
yield el
>>> list(flatten(d.values()))
['MRS', 'VAL', 'MRS', 'PRS', 'NTS']
然后,您可以使用計數器來計數每個字符串的出現次數:
>>> collections.Counter(flatten(d.values()))
Counter({'MRS': 2, 'NTS': 1, 'PRS': 1, 'VAL': 1})
正如已經發布的那樣,您可能可以使用collections.Counter
因為這是一種顯而易見的方法,或者您可以使用itertools.groupby
或itertools.groupby
和collections.Counter
的組合
只是itertools.groupby
>>> from itertools import groupby >>> a, b = [list(g) for _, g in groupby(d.values(), type)] >>> {k: len(list(g)) for k, g in groupby(sorted(a[0] + b))} {'NTS': 1, 'VAL': 1, 'PRS': 1, 'MRS': 2}
itertools.groupby
和collections.Counter
>>> from itertools import groupby >>> a, b = [list(g) for _, g in groupby(d.values(), type)] >>> dict(Counter(a[0] + b)) {'NTS': 1, 'VAL': 1, 'PRS': 1, 'MRS': 2}
這只是針對OP的問題所做的工作,盡管它並不可靠。
通常,您可以使用Counter
將鍵映射到計數-本質上是一個multiset 。
由於您的dict是多維的,因此您必須進行一些轉換,但是如果您簡單地遍歷dict中的每個值和子值並將其添加到Counter
實例中,您將獲得所需的內容。
這是一個首過實施; 根據d
將包含的內容,您可能需要對其進行一些調整:
counts = Counter()
for elem in d.values():
if isinstance(obj, Iterable) and not isinstance(elem, types.StringTypes):
for sub_elem in elem:
counter.add(sub_elem)
else:
counter.add(elem)
注意,我們檢查elem
是否是可迭代的,而不是字符串 。 Python並不容易區分字符串和集合,因此,如果您知道d
僅包含字符串和列表(例如),則可以簡單地執行isinstance(elem, list)
等。 如果不能保證d
的值都是列表(或元組等),最好顯式排除字符串。
同樣,如果d
可以包含遞歸鍵(例如,一個包含包含字符串的列表的列表),那將是不夠的; 您可能會想編寫一個遞歸函數來平整所有內容,例如dawg的解決方案。
我很懶,所以我將使用庫函數為我完成工作:
import itertools
import collections
d = {"a": ["MRS", "VAL"], "b": "PRS", "c": "MRS", "d": "NTS"}
values = [[x] if isinstance(x, basestring) else x for x in d.values()]
counter = collections.Counter(itertools.chain.from_iterable(values))
print counter
print counter['MRS'] # Sampling
輸出:
Counter({'MRS': 2, 'NTS': 1, 'PRS': 1, 'VAL': 1})
2
最后,計數器的作用類似於您想要的字典。
考慮這一行:
values = [[x] if isinstance(x, basestring) else x for x in d.values()]
在這里,我將字典d
中的每個值轉換為一個列表,以簡化處理。 values
可能類似於以下內容(順序可能不同,這很好):
# values = [['MRS', 'VAL'], ['MRS'], ['PRS'], ['NTS']]
接下來,表達式:
itertools.chain.from_iterable(values)
返回一個使列表變平的生成器,從概念上講,列表現在看起來像這樣:
['MRS', 'VAL', 'MRS', 'PRS', 'NTS']
最后,Counter類接受該列表並計數,因此我們得到了最終結果。
您可以通過內置函數來做到這一點:
>>> d = {"a":["MRS","VAL"],"b":"PRS","c":"MRS","d":"NTS"}
>>>
>>> flat = []
>>> for elem in d.values():
if isinstance(elem, list):
for sub_elem in elem:
flat.append(sub_elem)
else:
flat.append(elem)
>>> flat
['MRS', 'VAL', 'MRS', 'PRS', 'NTS']
>>>
>>> output = {}
>>>
>>> for item in flat:
output[item] = flat.count(item)
>>>
>>> output
{'NTS': 1, 'PRS': 1, 'VAL': 1, 'MRS': 2}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.