简体   繁体   English

蟒蛇和回文

[英]python and palindromes

i recently wrote a method to cycle through /usr/share/dict/words and return a list of palindromes using my ispalindrome(x) method here's some of the code...what's wrong with it? 我最近写了一个方法循环通过/usr/share/dict/words并使用我的ispalindrome(x)方法返回一个回文列表这里有一些代码......它有什么问题? it just stalls for 10 minutes and then returns a list of all the words in the file 它只会停顿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
wordlist = wl.readlines()

When you do this, there is a new line character at the end, so your list is like: 执行此操作时,最后会有一个换行符,因此您的列表如下:

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

the elements of which are obviously not a palindrome. 其元素显然不是回文。

You need this: 你需要这个:

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

So strip the newline character and it should be fine. 因此strip换行符,应该没问题。

To do this in one line: 要在一行中执行此操作:

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

EDIT: Iterating over a list and modifying it is causing problems. 编辑:迭代列表并修改它会导致问题。 Use a list comprehension,as pointed out by Matthew . 正如马修所指出的,使用列表理解。

I think there are two problems. 我认为有两个问题。

Firstly, what is the point in reading all of the words into a list? 首先,将所有单词读入列表有什么意义? Why not process each word in turn and print it if it's a palindrome. 为什么不依次处理每个单词并在它是回文时打印出来。

Secondly, watch out for whitespace. 其次,注意空白。 You have newlines at the end of each of your word s! 每个word的结尾都有换行符!

Since you're not identifying any palindromes (due to the whitespace), you're going to attempt to remove every item from the list. 由于您没有识别任何回文(由于空白),您将尝试从列表中删除所有项目。 While you're iterating over it! 当你在迭代它!

This solution runs in well under a second and identifies lots of palindromes: 这个解决方案在一秒钟内运行良好并识别出许多回文:

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

Edit : 编辑

Perhaps more 'pythonic' is to use generator expressions: 也许更多'pythonic'是使用生成器表达式:

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)

Others have already pointed out better solutions. 其他人已经指出了更好的解决方案。 I want to show you why the list is not empty after running your code. 我想告诉你为什么在运行代码后列表不为空。 Since your ispalindrome() function will never return True because of the "newlines problem" mentioned in the other answers, your code will call wordlist.remove(x) for every single item. 由于你的ispalindrome()函数永远不会返回True因为其他答案中提到的“换行问题”,你的代码将为每个项目调用wordlist.remove(x) So why is the list not empty at the end? 那么为什么列表最后不是空的?

Because you're modifying the list as you're iterating over it. 因为您在迭代时修改列表。 Consider the following: 考虑以下:

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

When you remove the 1 , the rest of the elements travels one step upwards, so now l[0] is 2 . 当你移除1 ,其余的元素向上移动一步,所以现在l[0]2 The iteration counter has advanced, though, and will look at l[1] in the next iteration and therefore remove 3 and so on. 迭代计数器已经提前了,并且将在下一次迭代中查看l[1] ,因此删除3 ,依此类推。

So your code removes half of the entries. 所以你的代码删除了一半的条目。 Moral: Never modify a list while you're iterating over it (unless you know exactly what you're doing :)). 道德:在迭代时不要修改列表(除非你确切地知道你正在做什么:))。

It doesn't return all the words. 它不会返回所有单词。 It returns half. 它返回一半。 This is because you're modifying the list while iterating over it, which is a mistake. 这是因为你在迭代它时修改列表,这是一个错误。 A simpler, and more effective solution, is to use a list comprehension. 一种更简单,更有效的解决方案是使用列表理解。 You can modify sukhbir's to do the whole thing: 你可以修改sukhbir来完成整个事情:

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

You can also break this up: 你也可以解决这个问题:

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

You're including the newline at the end of each word in /usr/share/dict/words . 您在/usr/share/dict/words的每个单词的末尾都包含换行符。 That means you never find any palindromes. 这意味着你永远找不到任何回文。 You'll speed things up if you just log the palindromes as you find them, instead of deleting non-palindromes from the list, too. 如果您只是在找到它们时记录回文,而不是从列表中删除非回文,您将加快速度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM