2011-01-12 132 views
2

我最近寫了一個方法來循環通過/usr/share/dict/words並返回一個迴文列表使用我的ispalindrome(x)方法 這裏的一些代碼...它有什麼問題嗎?它只是棚圈10分鐘,然後將文件蟒蛇和palindromes

 
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 
+2

「ispalindrome = lambda a:a [: - 1] .lower()== a.lower()`的更簡單的行內定義將爲您節省約25%的時間。 – eumiro 2011-01-12 08:01:38

+4

與你的問題無關,但你的第二個函數可以簡化爲`return(reverse(a).lower()== a.lower())`。 `==`已經返回`True`或`False`,所以不需要在它周圍包含`if`語句。 – 2011-01-12 08:03:08

回答

5
wordlist = wl.readlines() 

當你做到這一點,就在最後一個新行字符,所以你的列表是這樣的:

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

其中的元素顯然不是一個迴文。

你需要這樣的:

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

所以strip換行符,它應該被罰款。

要在一行做到這一點:

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

編輯:遍歷一個列表,並修改它導致的問題。使用列表理解,正如Matthew指出的那樣。

1

你包括每個單詞的/usr/share/dict/words末換行符在返回的所有單詞的列表。這意味着你永遠找不到任何迴文。如果您只是在找到它們時記錄迴文,而不是從列表中刪除非迴文,您會加快速度。

+0

這是真的,但它不能解釋爲什麼它會打印任何東西。 – 2011-01-12 07:54:32

3

我覺得有兩個問題。

首先,將所有單詞讀入列表有什麼意義?爲什麼不輪流處理每個單詞並在迴文中打印。

其次,注意空白。您在每個word s的末尾都有換行符!

由於您沒有識別任何迴文(由於空白),因此您將嘗試從列表中刪除每個項目。當你迭代它時!

將該溶液運行在井下的第二和識別許多回文:

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

編輯

也許更 'Python化' 是使用generator表達式:

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

它不會返回所有的單詞。它返回一半。這是因爲你在修改列表的同時迭代它,這是一個錯誤。更簡單,更有效的解決方案是使用列表理解。您可以修改薩克伯的做這件事:

[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)] 
3

其他人已經指出了更好的解決方案。我想告訴你爲什麼運行代碼後列表不是空的。由於您的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等等。

所以你的代碼刪除了一半的條目。道德:在迭代時不要修改列表(除非你確切知道你在做什麼:))。