Python умножить два счетчика коллекции
Счетчик коллекций Python Интересно, есть ли лучший способ сделать это? Переопределение метода класса Counter? Встроенное умножение дает точечное произведение двух счетчиков.
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})
3 ответа
Если предположить, a
а также b
всегда используйте одни и те же ключи, вы можете достичь этого с помощью словарного понимания следующим образом:
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})
Вы можете получить пересечение ключей, если у вас нет идентичных кодов:
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})
Или, если вы хотите присоединиться к обоим, вы можете или к dicts и использовать 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})
Это кажется немного лучше:
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})