如何将defaultdict与collection.Counter结合起来并保留Counter的操作

时间:2019-01-25 17:21:24

标签: python python-2.7

我从其他各种问题中提出了以下建议:

class RecurDefaultDict(Counter):
    def __init__(self, default_factory=Counter, *args, **kwargs):
        super(RecurDefaultDict, self).__init__(*args, **kwargs)
        self.default_factory = default_factory
    def __missing__(self, key):
        if self.default_factory is None:
            raise KeyError(key)
        val = self[key] = self.__class__(self.default_factory)
        return val

我要求满足以下条件。

oo = RecurDefaultDict()
uu = RecurDefaultDict()

oo[1][2][3] = 15
uu[1][2][4] = 20 

jj = oo+uu

但是我得到了:

>>> oo + uu
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "f:\ProgramData\Miniconda2\lib\collections.py", line 644, in __add__
    newcount = count + other[elem]
  File "f:\ProgramData\Miniconda2\lib\collections.py", line 644, in __add__
    newcount = count + other[elem]
  File "f:\ProgramData\Miniconda2\lib\collections.py", line 644, in __add__
    newcount = count + other[elem]
TypeError: unsupported operand type(s) for +: 'int' and 'RecurDefaultDict'

我知道问题在于类型不匹配。 但是,如果它们相同,它们将转换为Counter

>>> uu = RecurDefaultDict()
>>> oo = RecurDefaultDict()
>>> jj = uu + oo
Counter()

但是,即使它们恢复为Counter,它们也不会像Counter那样工作:

>>> oo = RecurDefaultDict()
>>> uu = RecurDefaultDict()
>>> oo[1][2] = 1
>>> uu[1][2] = 1
>>> oo + uu
Counter({1: Counter({2: 2})})
>>> jj = oo + uu
>>> jj + Counter()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "f:\ProgramData\Miniconda2\lib\collections.py", line 644, in __add__
    newcount = count + other[elem]
TypeError: unsupported operand type(s) for +: 'Counter' and 'int'
>>> jj
Counter({1: Counter({2: 2})})

可以做到吗?

要回答@blhsing: 这只是我正在计数的事物的子类型。原因是因为我不知道级别数。我需要能够做 total += counter 然后获得每个级别的所有重复部分的总计。 基本上,我想要这种行为:

jj = Counter()
jj["one"] = Counter({"ic":10, "au":15})
jj
Counter({'one': Counter({'au': 15, 'ic': 10})})
jj["two"] = Counter({"ic":10, "au":15})
jj
Counter({'two': Counter({'au': 15, 'ic': 10}), 'one': Counter({'au': 15, 'ic': 10})})
kk = Counter()
kk["two"] = Counter({"ic":99, "au":99})
kk+jj
Counter({'two': Counter({'au': 114, 'ic': 109}), 'one': Counter({'au': 15, 'ic': 10})})

但不必在每个级别创建一个Counter

0 个答案:

没有答案