簡體   English   中英

字典中最常用的值

[英]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.groupbyitertools.groupbycollections.Counter的組合

  1. 只是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} 
  2. itertools.groupbycollections.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM