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
È stato utile?

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 words!

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top