Python如何对两个计数器进行乘法运算?

5

Python集合计数器 想知道还有没有更好的方法。覆盖计数器类方法? 内置的乘法可以生成两个计数器的点积。

from collections import Counter
a = Counter({'b': 4, 'c': 2, 'a': 1})
b = Counter({'b': 8, 'c': 4, 'a': 2})    
newcounter = Counter()
for x in a.elements():
    for y in b.elements():
        if x == y:
             newcounter[x] = a[x]*b[y]

$ newcounter
Counter({'b': 32, 'c': 8, 'a': 2})

请注意,迭代.elements()会以任意顺序给出元素。除非a.elements()恰好与b.elements()相同,否则结果将毫无意义。您可能希望改为迭代sorted(a.keys()),然后计算a[key]*b[key] - smci
建议您将示例更改为 b = Counter({'c': 4, 'a': 2, 'b':8}),以强调这一点。 - smci
3个回答

6
假设 ab 总是有相同的键,你可以使用以下字典推导来实现这一点:
a = Counter({'b': 4, 'c': 2, 'a': 1})
b = Counter({'b': 8, 'c': 4, 'a': 2})
c = Counter({k:a[k]*b[k] for k in a})
print(c)

输出

Counter({'b': 32, 'c': 8, 'a': 2})

啊,是的,我想我最好删除这个评论,以免让其他人感到困惑。 - Sergei Lebedev

3

如果您没有相同的字典,您可以获取键的交集

from collections import Counter

a = Counter({'b': 4, 'c': 2, 'a': 1, "d":4})
b = Counter({'b': 8, 'c': 4, 'a': 2})

# just .keys() for python3
print Counter(({k: a[k] * b[k] for k in a.viewkeys() & b}))
Counter({'b': 32, 'c': 8, 'a': 2})

如果您想将两者结合起来,您可以将字典或使用dict.get:

from collections import Counter

a = Counter({'b': 4, 'c': 2, 'a': 1, "d":4})
b = Counter({'b': 8, 'c': 4, 'a': 2})


print Counter({k: a.get(k,1) * b.get(k, 1) for k in a.viewkeys() | b})
Counter({'b': 32, 'c': 8, 'd': 4, 'a': 2})

如果您想在计数器字典上使用 * 运算符,您需要自己编写:

class _Counter(Counter):
    def __mul__(self, other):
        return _Counter({k: self[k] * other[k] for k in self.viewkeys() & other})

a = _Counter({'b': 4, 'c': 2, 'a': 1, "d": 4})
b = _Counter({'b': 8, 'c': 4, 'a': 2})

print(a * b)

这将为您提供:

_Counter({'b': 32, 'c': 8, 'a': 2})

如果您想要就地更改:
from collections import Counter


class _Counter(Counter):
    def __imul__(self, other):
        return _Counter({k: self[k] * other[k] for k in self.viewkeys() & other})

输出:

In [28]: a = _Counter({'b': 4, 'c': 2, 'a': 1, "d": 4})

In [29]: b = _Counter({'b': 8, 'c': 4, 'a': 2})

In [30]: a *= b

In [31]: a
Out[31]: _Counter({'a': 2, 'b': 32, 'c': 8})

那个self.viewkeys()(可能)是我想要的。谢谢。我重载__mul__方法的第一个版本没有改变对象。 - codervince
1
不用担心,你可以在字典视图对象上使用多个集合操作 https://docs.python.org/2/library/stdtypes.html#dictionary-view-objects - Padraic Cunningham
1
无论何时出现collectionsitertools,你都会找到@PadraicCunningham.. :) - Iron Fist

1
这似乎好一些:
a = Counter({'b': 4, 'c': 2, 'a': 1})
b = Counter({'b': 8, 'c': 4, 'a': 2})    

newcounter = Counter({k:a[k]*v for k,v in b.items()})

>>> newcounter
Counter({'b': 32, 'c': 8, 'a': 2})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接