2011-08-22 9 views
5
from collections import * 
ignore = ['the','a','if','in','it','of','or'] 
ArtofWarCounter = Counter(ArtofWarLIST) 
for word in ArtofWarCounter: 
    if word in ignore: 
     del ArtofWarCounter[word] 

ArtofWarCounter è un oggetto Contatore contenente tutte le parole dell'Arte della Guerra. Sto cercando di eliminare le parole in ignore da ArtofWarCounter.Come rimuovo le voci all'interno di un oggetto contatore con un loop senza richiamare un RuntimeError?

Traceback:

File "<pyshell#10>", line 1, in <module> 
    for word in ArtofWarCounter: 
RuntimeError: dictionary changed size during iteration 

risposta

6

Per minime modifiche al codice, utilizzare list, in modo che l'oggetto si effettua l'iterazione viene disaccoppiato dal Counter

ignore = ['the','a','if','in','it','of','or'] 
ArtofWarCounter = Counter(ArtofWarLIST) 
for word in list(ArtofWarCounter): 
    if word in ignore: 
     del ArtofWarCounter[word] 

In python2, è possibile utilizzare ArtofWarCounter.keys() anziché list(ArtofWarCounter), ma quando è così semplice scrivi un codice che è a prova di futuro, perché non farlo?

Si tratta di una migliore idea di non solo contare gli elementi che si desidera ignorare

ignore = {'the','a','if','in','it','of','or'} 
ArtofWarCounter = Counter(x for x in ArtofWarLIST if x not in ignore) 

nota che ho fatto in un ignoreset che rende il test x not in ignore molto più efficiente

+0

Ottima risposta, grazie. Ho usato una piccola variazione: anziché per word in list (ArtofWarCounter), ho utilizzato ArtofWarLIST poiché sono essenzialmente la stessa cosa. Grazie! – Louis93

+0

@ Louis93, penso che "ArtofWarLIST' possa contenere duplicati, il che significa che dovrai ripetere più volte. Aggiungerò un modo migliore per la mia risposta –

1

vedere la seguente domanda del motivo per cui il metodo attuale non funziona:
Remove items from a list while iterating

In sostanza non si dovrebbe aggiungere o rimuovere elementi da una raccolta, mentre si sta loop su di esso . collections.Counter è una sottoclasse di dict, vedere il seguente avviso nella documentazione per dict.iteritems():

Using iteritems() while adding or deleting entries in the dictionary may raise a RuntimeError or fail to iterate over all entries.

+0

No, corre ad un errore. ArtofWarCounter [:] = [parola per parola in ArtofWarCounter se la parola non in ignorare] TypeError: Tipo di calcolo dell'hash Anche contatori sono una sottoclasse dict, quindi dubito che possano essere tagliati come le liste se non mi sbaglio – Louis93

+0

@ Louis93 - Sorry , Ero un po 'frettoloso nella mia risposta. Ho lasciato la spiegazione perché potrebbe essere ancora utile, una delle altre risposte dovrebbe darti una soluzione funzionante. –

-1

utilizzare un contatore, attraversare l'anello indietro (dall'ultimo al primo), rimuovere, se necessario. Loop fino a zero.

+0

Non sono sicuro di averlo capito, perché dovrebbe funzionare così dall'inizio alla fine? – Louis93

+0

Chiedo scusa, non ho molta familiarità con Python, ma mi sono occupato di questo problema "Raccolta modificata" in C# in questo modo. Avrei bisogno di usare un contatore per fare il ciclo attraverso la raccolta - tuttavia, non posso avviare il contatore da 0 a (n - 1). Questo perché, la mia condizione di fine per il ciclo fallirà se provo a eseguire il ciclo fino a (n - 1), quando avrei effettivamente cancellato alcuni tra 0 e (n - 1). Attraversare il backword del ciclo funzionerebbe in questi casi, perché la mia condizione di fine del ciclo (che è 0) funzionerà sempre. Inoltre, dal momento che comincio con (n - 1) come condizione del mio ciclo iniziale, non mi mancherà nessuno. – Arun

+0

Grazie Louis93 per averlo votato (due volte), mentre stavo semplicemente cercando di aiutarti! È improbabile che l'OP – Arun

11

Non ciclo su tutte le parole di un dict per trovare una voce, i dts sono molto più bravi nelle ricerche.

È un loop all'interno di lista ignore e rimuovere le voci che esistono:

ignore = ['the','a','if','in','it','of','or'] 
for word in ignore: 
    if word in ArtofWarCounter: 
     del ArtofWarCounter[word] 
+0

dovrebbe essere la risposta accettata. – Forethinker

Problemi correlati