питон и палиндромы - PullRequest
       15

питон и палиндромы

2 голосов
/ 12 января 2011

Я недавно написал метод для циклического перебора /usr/share/dict/words и возврата списка палиндромов, используя мой ispalindrome(x) метод. вот код ... что с ним не так? он просто останавливается на 10 минут, а затем возвращает список всех слов в файле

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

Ответы [ 5 ]

6 голосов
/ 12 января 2011
wordlist = wl.readlines()

Когда вы делаете это, в конце появляется символ новой строки, поэтому ваш список выглядит так:

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

элементы которого явно не являются палиндромом.

Вам нужно это:

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

Итак strip символ новой строки и все должно быть в порядке.

Для этого в одну строку:

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

РЕДАКТИРОВАТЬ: перебор списка и его изменение вызывает проблемы. Используйте понимание списка, как указано Мэтью .

3 голосов
/ 12 января 2011

Другие уже указали лучшие решения. Я хочу показать вам, почему список не пуст после запуска вашего кода. Так как ваша ispalindrome() функция никогда не вернет True из-за «проблемы перевода строки», упомянутой в других ответах, ваш код будет вызывать wordlist.remove(x) для каждого элемента. Так почему же список не пуст в конце?

Потому что вы изменяете список во время его перебора. Учтите следующее:

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

Когда вы удаляете 1, остальные элементы перемещаются на один шаг вверх, поэтому теперь l[0] равно 2. Счетчик итераций, однако, продвинулся и будет смотреть l[1] на следующей итерации, поэтому удалит 3 и т. Д.

Таким образом, ваш код удаляет половину записей. Мораль: никогда не изменяйте список во время итерации по нему (если вы точно не знаете, что делаете:)).

3 голосов
/ 12 января 2011

Я думаю, что есть две проблемы.

Во-первых, какой смысл читать все слова в списке? Почему бы не обработать каждое слово по очереди и не напечатать его, если это палиндром.

Во-вторых, остерегайтесь пробелов. У вас есть новые строки в конце каждого из ваших word s!

Поскольку вы не идентифицируете палиндромы (из-за пробелов), вы попытаетесь удалить каждый элемент из списка. Пока вы перебираете это!

Это решение работает менее чем за секунду и идентифицирует множество палиндромов:

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

Редактировать :

Возможно, более «питоническим» является использование генератора выражений:

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)
2 голосов
/ 12 января 2011

Он не возвращает все слова.Возвращает половину.Это потому, что вы изменяете список, перебирая его, что является ошибкой.Более простое и эффективное решение - использовать понимание списка.Вы можете изменить Сухбира, чтобы сделать все это:

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

Вы также можете разбить это:

stripped = (word.strip() for word in wl.readlines())
wordlist = [word for word in stripped if ispalindrome(word)]
1 голос
/ 12 января 2011

Вы включаете перевод строки в конце каждого слова в /usr/share/dict/words. Это означает, что вы никогда не найдете палиндромы. Вы ускорите ситуацию, если будете просто регистрировать палиндромы так, как вы их находите, вместо того, чтобы также удалять непалиндромы из списка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...