繁体   English   中英

唯一值的python字典计数

[英]python dictionary count of unique values

我在计算 Python 中每个键的不同值时遇到问题。

我有一本喜欢的字典

[{"abc":"movies"}, {"abc": "sports"}, {"abc": "music"}, {"xyz": "music"}, {"pqr":"music"}, {"pqr":"movies"},{"pqr":"sports"}, {"pqr":"news"}, {"pqr":"sports"}]

我需要单独打印每个键的不同值的数量。

这意味着我想打印

abc 3
xyz 1
pqr 4

请帮忙。

谢谢

回答 6 年后,有人向我指出我误读了这个问题。 虽然我的原始答案(如下)计算输入序列中的唯一,但实际上您有一个不同的计数差异问题 你想计算每个键的值

要计算每个键的唯一值,确切地说,您必须首先将这些值收集到集合中:

values_per_key = {}
for d in iterable_of_dicts:
    for k, v in d.items():
        values_per_key.setdefault(k, set()).add(v)
counts = {k: len(v) for k, v in values_per_key.items()}

对于您的输入,产生:

>>> values_per_key = {}
>>> for d in iterable_of_dicts:
...     for k, v in d.items():
...         values_per_key.setdefault(k, set()).add(v)
...
>>> counts = {k: len(v) for k, v in values_per_key.items()}
>>> counts
{'abc': 3, 'xyz': 1, 'pqr': 4}

如果您想使用此类提供的附加功能,我们仍然可以将该对象包装在Counter()实例中,请参见下文:

>>> from collections import Counter
>>> Counter(counts)
Counter({'pqr': 4, 'abc': 3, 'xyz': 1})

缺点是如果您的输入迭代非常大,上述方法可能需要大量内存。 如果您不需要精确的计数,例如当数量级足够时,还有其他方法,例如超级日志结构或其他“草绘”流计数的算法。

这种方法要求您安装第 3 方库。 例如, datasketch项目同时提供HyperLogLogMinHash 这是一个 HLL 示例(使用HyperLogLogPlusPlus类,这是对 HLL 方法的最新改进):

from collections import defaultdict
from datasketch import HyperLogLogPlusPlus

counts = defaultdict(HyperLogLogPlusPlus)

for d in iterable_of_dicts:
    for k, v in d.items():
        counts[k].update(v.encode('utf8'))

在分布式设置中,您可以使用Redis 来管理 HLL 计数


我原来的回答

使用collections.Counter()实例,以及一些链接:

from collections import Counter
from itertools import chain

counts = Counter(chain.from_iterable(e.keys() for e in d))

这可确保正确计算输入列表中具有多个键的词典。

演示:

>>> from collections import Counter
>>> from itertools import chain
>>> d = [{"abc":"movies"}, {"abc": "sports"}, {"abc": "music"}, {"xyz": "music"}, {"pqr":"music"}, {"pqr":"movies"},{"pqr":"sports"}, {"pqr":"news"}, {"pqr":"sports"}]
>>> Counter(chain.from_iterable(e.keys() for e in d))
Counter({'pqr': 5, 'abc': 3, 'xyz': 1})

或在输入字典中使用多个键:

>>> d = [{"abc":"movies", 'xyz': 'music', 'pqr': 'music'}, {"abc": "sports", 'pqr': 'movies'}, {"abc": "music", 'pqr': 'sports'}, {"pqr":"news"}, {"pqr":"sports"}]
>>> Counter(chain.from_iterable(e.keys() for e in d))
Counter({'pqr': 5, 'abc': 3, 'xyz': 1})

Counter()具有其他有用的功能,例如.most_common()方法,该方法以反向排序的顺序列出元素及其计数:

for key, count in counts.most_common():
    print '{}: {}'.format(key, count)

# prints
# 5: pqr
# 3: abc
# 1: xyz

无需使用计数器。 您可以通过这种方式实现:

# input dictionary
d=[{"abc":"movies"}, {"abc": "sports"}, {"abc": "music"}, {"xyz": "music"}, {"pqr":"music"}, {"pqr":"movies"},{"pqr":"sports"}, {"pqr":"news"}, {"pqr":"sports"}]

# fetch keys
b=[j[0] for i in d for j in i.items()]

# print output
for k in list(set(b)):
    print "{0}: {1}".format(k, b.count(k))

您所描述的内容——每个键都有多个值的列表——最好通过以下方式进行可视化:

{'abc': ['movies', 'sports', 'music'],
 'xyz': ['music'],
 'pqr': ['music', 'movies', 'sports', 'news']
}

在这种情况下,您必须做更多的工作才能插入:

  1. 查找键以查看它是否已经存在
    • 如果不存在,则创建值为[]新键(空列表)
  2. 检索值(与键关联的列表)
  3. 使用if value in查看被检查的值是否存在于列表中
  4. 如果新值不在, .append()

这也导致了一种计算存储元素总数的简单方法:

# Pseudo-code
for myKey in myDict.keys():
    print "{0}: {1}".format(myKey, len(myDict[myKey])
>>> d = [{"abc":"movies"}, {"abc": "sports"}, {"abc": "music"}, {"xyz": "music"},
... {"pqr":"music"}, {"pqr":"movies"},{"pqr":"sports"}, {"pqr":"news"}, 
... {"pqr":"sports"}]
>>> from collections import Counter
>>> counts = Counter(key for dic in d for key in dic.keys())
>>> counts
Counter({'pqr': 5, 'abc': 3, 'xyz': 1})
>>> for key in counts:
...     print (key, counts[key])
...
xyz 1
abc 3
pqr 5

使用 collections.Counter。 假设你有一个单项字典的列表......

from collections import Counter
listOfDictionaries = [{'abc':'movies'}, {'abc':'sports'}, {'abc':'music'},
    {'xyz':'music'}, {'pqr':'music'}, {'pqr':'movies'},
    {'pqr':'sports'}, {'pqr':'news'}, {'pqr':'sports'}]
Counter(list(dict)[0] for dict in zzz)

建立在@akashdeep 解决方案的基础上,该解决方案使用该集合但给出了错误的结果,因为不考虑问题中提到的“不同”要求( pqr应该是 4,而不是 5)。

# dictionary
d=[{"abc":"movies"}, {"abc": "sports"}, {"abc": "music"}, {"xyz": "music"}, {"pqr":"music"}, {"pqr":"movies"},{"pqr":"sports"}, {"pqr":"news"}, {"pqr":"sports"}]

# merged dictionary
c = {}
for i in d:
    for k,v in i.items():
        try:
            c[k].append(v)
        except KeyError:
            c[k] = [v]

# counting and printing
for k,v in c.items():
    print "{0}: {1}".format(k, len(set(v)))

这将给出正确的:

xyz: 1
abc: 3
pqr: 4

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM