Question

i a récemment écrit une méthode pour faire défiler /usr/share/dict/words et retourner une liste de palindromes en utilisant ma méthode de ispalindrome(x) voici une partie du code ... ce qui ne va pas avec elle? il cale juste pour 10 minutes, puis retourne une liste de tous les mots dans le fichier

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
Était-ce utile?

La solution

wordlist = wl.readlines()

Quand vous faites cela, il y a un caractère de nouvelle ligne à la fin, de sorte que votre liste est comme:

['eye\n','bye\n', 'cyc\n']

les éléments qui sont évidemment pas un palindrome.

Vous en avez besoin:

['eye','bye', 'cyc']

strip le caractère et il devrait newline bien.

Pour faire cela en une ligne:

wordlist = [line.strip() for line in open('/usr/share/dict/words')]

EDIT: Enumérer les une liste et la modifier est à l'origine des problèmes. Utilisez une compréhension de la liste, comme en pointe par Matthieu .

Autres conseils

D'autres ont déjà signalé de meilleures solutions. Je veux vous montrer pourquoi la liste n'est pas vide après l'exécution de votre code. Étant donné que votre fonction ispalindrome() ne reviendra True à cause du « problème des sauts de ligne » mentionné dans les autres réponses, votre code appellera wordlist.remove(x) pour chaque article. Alors, pourquoi la liste ne vide à la fin?

Parce que vous modifiez la liste que nous parcourons dessus. Considérez ce qui suit:

>>> l = [1,2,3,4,5,6]
>>> for i in l:
...     l.remove(i)
...
>>> l
[2, 4, 6]

Lorsque vous supprimez le 1, le reste des éléments se déplace d'un pas vers le haut, maintenant l[0] est 2. Le compteur d'itération a avancé, cependant, et se penchera sur l[1] dans l'itération suivante et donc supprimer 3 et ainsi de suite.

Ainsi, votre code supprime la moitié des entrées. Moralité: Ne jamais modifier une liste alors que nous parcourons dessus (sauf si vous savez exactement ce que vous faites:).)

Je pense qu'il ya deux problèmes.

Tout d'abord, quel est le point de lire tous les mots dans une liste? Pourquoi ne pas traiter chaque mot à son tour et l'imprimer si c'est un palindrome.

En second lieu, attention aux espaces. Vous avez des nouvelles lignes à la fin de chacun de vos words!

Puisque vous n'êtes pas identifier les palindromes (en raison du espace), vous allez tenter de supprimer tous les éléments de la liste. Alors que nous parcourons dessus!

Cette solution fonctionne en moins d'une seconde et identifie beaucoup de palindromes:

for word in open('/usr/share/dict/words', 'r'):
    word = word.strip()
    if ispalindrome(word):
        print word

Modifier :

Peut-être plus 'pythonique' est d'utiliser des expressions générateur :

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)

Il ne retourne pas tous les mots. Elle retourne la moitié. En effet, vous modifiez la liste en itérer sur elle, ce qui est une erreur. Une simple et plus efficace solution, consiste à utiliser une liste de compréhension. Vous pouvez modifier sukhbir est de faire la chose:

[word for word in (word.strip() for word in wl.readlines()) if ispalindrome(word)]

Vous pouvez aussi briser ce haut:

stripped = (word.strip() for word in wl.readlines())
wordlist = [word for word in stripped if ispalindrome(word)]

Vous y compris la nouvelle ligne à la fin de chaque mot dans /usr/share/dict/words. Cela signifie que vous ne trouverez jamais des palindromes. Vous accélérer les choses si vous vous connectez simplement les palindromes que vous les trouverez, au lieu de supprimer non palindromes dans la liste, aussi.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top