2012-04-18 8 views
9

Me gustaría comparar elementos en un diccionario entre sí, y eliminar los elementos de acuerdo a algunos criterios de comparación. Y me encantaría que sea eficiente. Tengo una función que puede hacer esto, pero copia repetidamente el dictionay. Seguramente no es una forma superior:Comparar un dict a sí mismo y eliminar claves similares de manera eficiente

mydict = {1:5,2:7,3:9,4:9,7:7,8:0,111:43,110:77} 

def partial_duplicate_destroyer(mydict,tolerance): 
    for key1 in mydict.keys(): 
     mydict_copy = mydict.copy() 
     for key2 in mydict_copy.keys(): 
      if key2 - tolerance < key1 < key2 + tolerance and not(key1 == key2): 
       del(mydict[key1]) 
       break 
    return mydict 

print partial_duplicate_destroyer(mydict,2) 
print partial_duplicate_destroyer(mydict,20) 
print partial_duplicate_destroyer(mydict,200) 

#correct output: 
# {4: 9, 8: 0, 111: 43} 
# {8: 0, 111: 43} 
# {111: 43} 
+2

Si hay un par de claves dentro de la tolerancia entre ellas, ¿qué importancia tiene eliminarse? –

+0

@David Robinson - No, no, pero en el ejemplo anterior cuando la tolerancia = 2, solo debe permanecer una clave de 1,2,3,4. – fraxel

Respuesta

6

Este enfoque podría reducirse a:

from itertools import combinations 

def partial_duplicate_destroyer(mydict, tolerance): 
    #Modifies in-place. Returns only as a convenience. Copy if you don't want this behaviour. 
    for key1, key2 in combinations(mydict, 2): 
     if key1 in mydict and key2 - tolerance < key1 < key2 + tolerance: 
     del mydict[key1] 
    return mydict 

Si tratamos esto:

>>> mydict = {1:5,2:7,3:9,4:9,7:7,8:0,111:43,110:77} 
>>> partial_duplicate_destroyer(mydict, 2) 
{4: 9, 8: 0, 111: 43} 
>>> partial_duplicate_destroyer(mydict, 20) 
{8: 0, 111: 43} 
>>> partial_duplicate_destroyer(mydict, 200) 
{111: 43} 
>>> mydict 
{111: 43} 

Este utiliza itertools.combinations() para producir todas las combinaciones posibles de teclas (sin repetir). Esto es mucho más eficiente ya que no te molesta trabajar donde tienes las mismas teclas, y se hace de manera más eficiente en C que en tu lado con Python.

Tenga en cuenta que aquí se está modificando mydict en su lugar - es decir, al final de este, mydict es {111: 43} - es necesario copiar el dict y trabajar en él en la función, en lugar de hacerlo directamente en ella, si no' quiero este comportamiento Esto es lo que se muestra en la última línea.

+0

Eso se ve genial, y su primera versión con 'product' también parecía estar bien. – fraxel

+0

@fraxel El producto funcionó, pero significaba que tenía que filtrar manualmente los resultados repetidos y los resultados donde las claves eran las mismas. Usar combinaciones será más rápido y no dará los resultados que no necesita, reduciendo los controles que necesita hacer: ganar-ganar. –

+0

Gran trabajo, muchas gracias :) – fraxel

Cuestiones relacionadas