2012-04-18 12 views
9

Vorrei confrontare gli elementi di un dizionario tra loro e rimuovere elementi in base ad alcuni criteri di confronto. E mi piacerebbe che fosse efficiente. Ho una funzione che può farlo, ma copia ripetutamente il dizionario. Sicuramente c'è un modo superiore:Confronta un dettato a se stesso e rimuovi le chiavi simili in modo efficiente

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

Se ci sono una coppia di chiavi entro la tolleranza reciproca, è importante la cancellazione? –

+0

@David Robinson - No, non è vero, ma nell'esempio sopra quando la tolleranza = 2, dovrebbe rimanere una sola chiave su 1,2,3,4. – fraxel

risposta

6

Questo approccio potrebbe essere ridotta fino 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 

Se proviamo questo:

>>> 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} 

Questo utilizza itertools.combinations() per la produzione di tutte le possibili combinazioni di chiavi (senza ripetere). Questo è molto più efficiente in quanto non ti preoccupi di lavorare dove hai le chiavi allo stesso modo, ed è fatto in modo più efficiente in C piuttosto che in Python.

Si noti che qui si sta modificando mydict sul posto - che è alla fine di questo, mydict è {111: 43} - è necessario copiare il dict e lavorare su di essa in funzione, piuttosto che direttamente su di esso, se si don' voglio questo comportamento Questo è ciò che è mostrato nell'ultima riga.

+0

Questo è un ottimo aspetto e anche la tua prima versione con 'prodotto' sembrava soddisfacente. – fraxel

+0

@fraxel Il prodotto ha funzionato, ma significava che dovevi filtrare manualmente risultati e risultati ripetuti dove le chiavi erano le stesse. Usare le combinazioni sarà più veloce e non dare risultati che non ti servono, riducendo i controlli che devi fare - win-win. –

+0

Ottimo lavoro, molte grazie :) – fraxel

Problemi correlati