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)
注意,我们检查elemis an iterable and not a string。Python不容易区分字符串和集合,所以如果您知道d将只包含字符串和列表(例如),您可以简单地执行isinstance(elem, list)等等。如果不能保证d的值都是列表(或元组,等等),那么最好显式地排除字符串。在
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']
>>> 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和{}
>>> 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}
一般来说,您可以使用^{} 将键映射到计数-它本质上是一个multiset。在
因为dict是多维的,所以您需要进行一些转换,但是如果您只需迭代dict中的每个值和子值,并将其添加到
Counter
实例中,您将得到您想要的结果。在这是一个第一步实现;根据
d
将包含的内容,您可能需要稍微调整一下:注意,我们检查
elem
is an iterable and not a string。Python不容易区分字符串和集合,所以如果您知道d
将只包含字符串和列表(例如),您可以简单地执行isinstance(elem, list)
等等。如果不能保证d
的值都是列表(或元组,等等),那么最好显式地排除字符串。在另外,如果
d
可以包含递归键(例如,包含包含字符串的列表的列表),这是不够的;您可能需要编写一个递归函数来展开所有内容,就像dawg的解决方案一样。在由于dict由字符串和字符串列表组成,因此首先需要将这些元素flatten转换为一种常见的字符串类型:
然后可以使用Counter来计算每个字符串的出现次数:
^{pr2}$如前所述,您可以使用}和{}的组合
collections.Counter
,因为这是一种显而易见的方法,或者您可以使用itertools.groupby
或{只要
itertools.groupby
itertools.groupby
和{这只是解决了OP存在的问题,但并不健壮。在
相关问题 更多 >
编程相关推荐