pitone e palindromi
-
10-10-2019 - |
Domanda
Recentemente ho scritto un metodo per scorrere /usr/share/dict/words
e restituire una lista di palindromi usando il mio metodo ispalindrome(x)
ecco una parte del codice ... che cosa c'è che non va? solo stalle per 10 minuti e poi restituisce un elenco di tutte le parole nel file
def reverse(a): return a[::-1] def ispalindrome(a): b = reverse(a) if b.lower() == a.lower(): return True else: return False wl = open('/usr/share/dict/words', 'r') wordlist = wl.readlines() wl.close() for x in wordlist: if not ispalindrome(x): wordlist.remove(x) print wordlist
Soluzione
wordlist = wl.readlines()
Quando si esegue questa operazione, c'è un carattere di nuova riga alla fine, così il vostro elenco è simile:
['eye\n','bye\n', 'cyc\n']
i cui elementi non sono ovviamente un palindromo.
Hai bisogno di questo:
['eye','bye', 'cyc']
Quindi strip
il carattere di nuova riga e dovrebbe andare bene.
Per fare questo in una sola riga:
wordlist = [line.strip() for line in open('/usr/share/dict/words')]
EDIT: l'iterazione di un elenco e la modifica sta causando problemi. Utilizzare un elenco di comprensione, come fuori punte da Matthew .
Altri suggerimenti
altri hanno già fatto notare soluzioni migliori. Voglio mostrarvi perché l'elenco non è vuoto dopo l'esecuzione il codice. Dal momento che la funzione ispalindrome()
non tornerà mai True
a causa del "problema a capo" di cui parla nelle altre risposte, il tuo codice chiamerà wordlist.remove(x)
per ogni singolo articolo. Allora, perché è la lista non vuota alla fine?
Perché si sta modificando la lista come sei iterazione su di esso. Si consideri il seguente:
>>> l = [1,2,3,4,5,6]
>>> for i in l:
... l.remove(i)
...
>>> l
[2, 4, 6]
Quando si rimuove il 1
, il resto degli elementi viaggia un passo verso l'alto, così ora è l[0]
2
. Il contatore di iterazione ha avanzato, però, e esaminerà l[1]
nella successiva iterazione e quindi rimuovere 3
e così via.
Quindi, il codice elimina la metà delle voci. Morale: Non modificare una lista, mentre si sta iterando su di esso (a meno che non si sa esattamente cosa si sta facendo:)).
Penso che ci siano due problemi.
In primo luogo, qual è il punto in letto tutte le parole in una lista? Perché non trattare ogni parola a sua volta e stamparlo se si tratta di un palindromo.
In secondo luogo, attenzione per gli spazi bianchi. Avete a capo alla fine di ciascuno dei vostri word
s!
Dal momento che non stai individuare eventuali palindromi (a causa della spazio bianco), si sta andando a tentare di rimuovere ogni elemento dall'elenco. Mentre siete l'iterazione su di esso!
Questa soluzione viene eseguito in ben al di sotto di un secondo e identifica un sacco di palindromi:
for word in open('/usr/share/dict/words', 'r'):
word = word.strip()
if ispalindrome(word):
print word
Modifica :
Forse più 'divinatorio' è quello di utilizzare generatore espressioni:
def ispalindrome(a):
return a[::-1].lower() == a.lower()
words = (word.strip() for word in open('/usr/share/dict/words', 'r'))
palindromes = (word for word in words if ispalindrome(word))
print '\n'.join(palindromes)
E non restituisce tutte le parole. Esso restituisce la metà. Questo perché si sta modificando la lista, mentre l'iterazione su di esso, che è un errore. Una soluzione più semplice e più efficace, è quello di utilizzare un elenco di comprensione. È possibile modificare Sukhbir a che fare il tutto:
[word for word in (word.strip() for word in wl.readlines()) if ispalindrome(word)]
Si può anche rompere questo fino:
stripped = (word.strip() for word in wl.readlines())
wordlist = [word for word in stripped if ispalindrome(word)]
Stai compresa la nuova riga alla fine di ogni parola in /usr/share/dict/words
. Ciò significa che non trovate qualche palindromi. Potrai accelerare le cose solo se si accede i palindromi come li trovate, invece di cancellare i non palindromi dalla lista, anche.