Estoy trabajando en un algoritmo en Python que tomaría la entrada del usuario y les diría qué letras nuevas necesitarían agregar a una cadena para convertirla en una cadena diferente, y he estado jugando mucho con los diccionarios creados por El método de contador.

Quiero comparar dos diccionarios diferentes que cuentan letras de cadenas (como los objetos devueltos al usar la herramienta Contador del módulo de colecciones). Podemos llamar a estos diccionarios D1 y D2. Quiero que haya dos diccionarios resultantes (R1 y R2), el primero son las letras compartidas entre los dos, y el segundo son las letras necesarias para convertir R1 en R2 (las letras que están en D2 pero no en D1).

Por ejemplo:

# assuming they’ve been converted from counter objects into regular 
dictionaries #

D1 = {‘A’: 2, ‘B’: 1, ‘C’: 4, ‘D’: 5}
D2 = {‘A’: 3, ‘B’: 4, ‘C’ : 4, ‘D’: 7}

# Some sort of comparison function executed here #

Resultado:

R1={‘A’: 2, ‘B’: 3, ‘C’: 4, ‘D’: 5} 
R2 = {‘A’: 1, ‘B’: 1, ‘C’: 0 , ‘D’: 2} 
7
Nick Hart 14 sep. 2018 a las 04:50

4 respuestas

La mejor respuesta

Si por letras compartidas te refieres a la intersección del Contador, puedes usar el operador & y la cantidad de letras necesarias para convertir R1 en R2 puede verse como la diferencia:

from collections import Counter

D1 = Counter({'A': 2, 'B': 1, 'C': 4, 'D': 5})
D2 = Counter({'A': 3, 'B': 4, 'C': 4, 'D': 7})

R1 = D1 & D2

print(R1)  # intersection:  min(c[x], d[x])
print(D2 - D1)  # subtract (keeping only positive counts)

Salida

Counter({'D': 5, 'C': 4, 'A': 2, 'B': 1})
Counter({'B': 3, 'D': 2, 'A': 1})

Si desea mantener conteos negativos, puede hacerlo así:

from collections import Counter

D1 = Counter({'A': 2, 'B': 1, 'C': 4, 'D': 5, 'E': 5})
D2 = Counter({'A': 3, 'B': 4, 'C': 4, 'D': 7, 'E': 3})

R2 = Counter({key: D2.get(key, 0) - value for key, value in D1.items()})
print(R2)

Salida

Counter({'B': 3, 'D': 2, 'A': 1, 'C': 0, 'E': -2})

En el ejemplo anterior 'E' : -2 porque el recuento de E es 5 en D1 y 3 en D2. Nota: todos los ejemplos están en Python 3.5.

7
Dani Mesejo 14 sep. 2018 a las 02:17

No pude entender la pregunta, pero desde mi entendimiento:

R1 = {k: min(v, D2[k]) for k, v in D1.items()}
R2 = {k: abs(v - D2[k]) for k, v in D1.items()}

Resultado

>>> {k: min(v, D2[k]) for k, v in D1.items()}
{'A': 2, 'B': 1, 'C': 4, 'D': 5}
>>> {k: abs(v - D2[k]) for k, v in D1.items()}
{'A': 1, 'B': 3, 'C': 0, 'D': 2}
0
user10356004user10356004 14 sep. 2018 a las 01:59
IntersectCounter=[]
for each in D1:
        if D1[each]==D2[each]:
              IntersectCounter.append(each)

Esto proporciona contenido común en los contadores D1 y D2.

1
alanpaivaa 6 abr. 2019 a las 23:08

Esas operaciones ya están integradas en el tipo de contador:

Se proporcionan varias operaciones matemáticas para combinar objetos Counter para producir multisets (contadores que tienen conteos mayores que cero). La suma y la resta combinan contadores sumando o restando los recuentos de elementos correspondientes. La intersección y la unión devuelven el mínimo y el máximo de los recuentos correspondientes.

(Citado de Python collections.Counter docs.)

Asumiendo que D1 y D2 son contadores, intente

R1 = D1 & D2
R2 = D2 - R1
3
rici 14 sep. 2018 a las 02:05