[英]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
项目同时提供HyperLogLog和MinHash 。 这是一个 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']
}
在这种情况下,您必须做更多的工作才能插入:
[]
新键(空列表)if value in
查看被检查的值是否存在于列表中.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.