用于创建defaultdictionary计数器的大多数Pythonic方法

时间:2017-03-01 11:50:08

标签: python

我正在尝试根据条件计算各种项目的出现次数。到目前为止我所拥有的这个函数给出了两个项目会增加计数器:

给定[('a', 'a'), ('a', 'b'), ('b', 'a')]output defaultdict(<class 'collections.Counter'>, {'a': Counter({'a': 1, 'b': 1}), 'b': Counter({'a': 1})

该功能可以在下面看到

def freq(samples=None):
    out = defaultdict(Counter)
    if samples:
        for (c, s) in samples:
            out[c][s] += 1
    return out

虽然仅限于使用元组,但我希望它更通用并且可以处理任意数量的变量,例如,[('a', 'a', 'b'), ('a', 'b', 'c'), ('b', 'a', 'a')]仍然有效,我可以查询结果让我们说res['a']['b']并获取'c'的计数。

在Python中执行此操作的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

假设列表中的所有元组具有相同的长度:

from collections import Counter
from itertools import groupby
from operator import itemgetter
def freq(samples=[]):
    sorted_samples = sorted(samples)
    if sorted_samples and len(sorted_samples[0]) > 2:
        return {key: freq(value[1:] for value in values) for key, values in groupby(sorted_samples, itemgetter(0))}
    else:
        return {key: Counter(value[1] for value in values) for key, values in groupby(sorted_samples, itemgetter(0))}

这给出了:

freq([('a', 'a'), ('a', 'b'), ('b', 'a'), ('a', 'c')])
>>> {'a': Counter({'a': 1, 'b': 1, 'c': 1}), 'b': Counter({'a': 1})}

freq([('a', 'a', 'a'), ('a', 'b', 'c'), ('b', 'a', 'a'), ('a', 'c', 'c')])
>>> {'a': {'a': Counter({'a': 1}), 'b': Counter({'c': 1}), 'c': Counter({'c': 1})}, 'b': {'a': Counter({'a': 1})}}

答案 1 :(得分:0)

一种选择是使用完整的元组作为键

def freq(samples=[]):
    out = Counter()
    for sample in samples:
         out[sample] += 1
    return out

然后将事物作为

返回
Counter({('a', 'a', 'b'): 1, ('a', 'b', 'c'): 1, ('b', 'a', 'a'): 1})

您可以将元组转换为字符串以选择某些切片,例如"('a', 'b',"。例如,在新词典{k: v for k,v in out.items() if str(k)[:10] == "('a', 'b',"}中。

如果这些组的长度确实是2或3,但两者都不是,则可以更改为:

def freq(samples):
    l = len(samples[0])
    if l == 2:
        out = defaultdict(lambda: 0)
        for a, b in samples:
             out[a][b] += 1
    elif l == 3:
        out = defaultdict(lambda: defaultdict(lambda: 0))
        for a, b, c in samples:
            out[a][b][c] += 1
    return out