Por ejemplo, tengo dos dictados:
Dict A: {'a': 1, 'b': 2, 'c': 3}
Dict B: {'b': 3, 'c': 4, 'd': 5}
Necesito una forma pitónica de 'combinar' dos dictados de modo que el resultado sea:
{'a': 1, 'b': 5, 'c': 7, 'd': 5}
Es decir: si una clave aparece en ambos dictados, agregue sus valores, si aparece en un solo dict, mantenga su valor.
python
dictionary
Derrick Zhang
fuente
fuente
sum(counters)
no funciona, desafortunadamentesum()
un valor inicial, consum(counters, Counter())
.+=
hacer una suma in situ.res = counters[0]
entoncesfor c in counters[1:]: res += c
.update()
en lugar de+=
:for c in counters[1:]: res.update(c)
.Una solución más genérica, que también funciona para valores no numéricos:
o incluso más genérico:
Por ejemplo:
fuente
for k in b.viewkeys() & a.viewkeys()
, cuando usa Python 2.7 , y omitir la creación de conjuntos.set(a)
devuelve el conjunto de claves en lugar de un conjunto de tuplas? ¿Cuál es la razón de esto?list({..})
,for k in {...}
etcoperator.mul
dejar claro que este código es genérico y no se limita a agregar números.{**a, **b, **{k: op(a[k], b[k]) for k in a.keys() & b}}
debería funcionar en Python 3.5+.fuente
for x in set(itertools.chain(A, B))
sería más lógico usar ? Como usar set on dict es un poco absurdo ya que las teclas ya son únicas? Sé que es solo otra forma de obtener un conjunto de claves, pero me resulta más confuso que usarloitertools.chain
(lo que implica que sabes lo queitertools.chain
hace)Introducción: Existen las (probablemente) mejores soluciones. Pero debe saberlo y recordarlo, y a veces tiene que esperar que su versión de Python no sea demasiado antigua o sea cual sea el problema.
Luego están las soluciones más 'hacky'. Son geniales y cortos, pero a veces son difíciles de entender, leer y recordar.
Sin embargo, existe una alternativa que consiste en intentar reinventar la rueda. - ¿Por qué reinventar la rueda? - Generalmente porque es una muy buena manera de aprender (y a veces solo porque la herramienta ya existente no hace exactamente lo que le gustaría y / o como le gustaría) y la forma más fácil si no sabe o No recuerdo la herramienta perfecta para su problema.
Por lo tanto , propongo reinventar la rueda de la
Counter
clase desde elcollections
módulo (al menos parcialmente):Probablemente habría otra forma de implementar eso y ya hay herramientas para hacerlo, pero siempre es bueno visualizar cómo funcionarían las cosas básicamente.
fuente
fuente
¡El que no tiene importaciones adicionales!
Es un estándar pitónico llamado EAFP (más fácil de pedir perdón que permiso). El siguiente código se basa en ese estándar de Python .
EDITAR: gracias a jerzyk por sus sugerencias de mejora.
fuente
Definitivamente, sumar la
Counter()
s es la forma más pitónica en tales casos, pero solo si resulta en un valor positivo . Aquí hay un ejemplo y, como puede ver, no hay ningúnc
resultado después de negar elc
valor delB
diccionario.Esto se debe a que los
Counter
s se diseñaron principalmente para trabajar con enteros positivos para representar recuentos en ejecución (el recuento negativo no tiene sentido). Pero para ayudar con esos casos de uso, python documenta el rango mínimo y las restricciones de tipo de la siguiente manera:Entonces, para solucionar ese problema después de sumar su Contador, puede usarlo
Counter.update
para obtener el resultado deseado. Funciona comodict.update()
pero agrega conteos en lugar de reemplazarlos.fuente
O
Alternativa que puede usar Counter como @Martijn ha mencionado anteriormente.
fuente
Para una forma más genérica y extensible, verifique mergedict . Utiliza
singledispatch
y puede fusionar valores en función de sus tipos.Ejemplo:
fuente
Desde python 3.5: fusión y suma
Gracias a @tokeinizer_fsj que me dijo en un comentario que no entendí completamente el significado de la pregunta (pensé que agregar solo significaba agregar claves que eventualmente eran diferentes en los dos dictadores y, en cambio, quería decir que los valores clave comunes debe resumirse) Así que agregué ese ciclo antes de la fusión, para que el segundo diccionario contenga la suma de las claves comunes. El último diccionario será aquel cuyos valores durarán en el nuevo diccionario que es el resultado de la fusión de los dos, así que creo que el problema está resuelto. La solución es válida desde python 3.5 y las siguientes versiones.
Código reutilizable
fuente
b
es5
(2 + 3), pero su método está regresando3
.Además, tenga en cuenta que
a.update( b )
es 2 veces más rápido quea + b
fuente
Podrías generalizar esto fácilmente:
Entonces puede tomar cualquier cantidad de dictados.
fuente
Esta es una solución simple para fusionar dos diccionarios donde
+=
se pueden aplicar a los valores, tiene que iterar sobre un diccionario solo una vezfuente
Esta solución es fácil de usar, se usa como un diccionario normal, pero puede usar la función de suma.
fuente
Qué pasa:
Salida:
fuente
Las soluciones anteriores son excelentes para el escenario donde tiene una pequeña cantidad de
Counter
s. Sin embargo, si tiene una gran lista de ellos, algo como esto es mucho mejor:La solución anterior está esencialmente sumando la
Counter
s por:Esto hace lo mismo, pero creo que siempre ayuda ver lo que efectivamente está haciendo debajo.
fuente
Fusionar tres dictados a, b, c en una sola línea sin ningún otro módulo o libs
Si tenemos los tres dictados
Fusionar todo con una sola línea y devolver un objeto dict usando
Volviendo
fuente
{'a': 9, 'b': 9, 'd': 90}
. Te estás perdiendo el requisito de "suma".