2015-07-28 45 views
3

我下面的Codecademy網站的教程,問題是「定義一個函數調用anti_vowel,它有一個字符串,文本,輸入並返回全部拆除元音的文本Python中,我錯誤的函數來刪除字符串中的元音?

例如:anti_vowel(」嘿,你!「)應該返回」Hy Y!「。」

代碼:「它返回!

def anti_vowel(text): 
    textlist = list(text) 
    print textlist 
    for k in textlist: 
     if k in"aeiouAEIOU": 
      print k 
      textlist.remove(k) 
    return "".join(textlist) 

的錯誤是「哎呀,再試一次就anti_vowel你的函數失敗(」嘿!看字)‘海蘭LK詞’的時候,它應該返回」 Hy lk Wrds!「。」
我不知道爲什麼仍然有一個額外的'o'在那裏?誰能告訴我是什麼原因造成的錯誤?謝謝!

+6

因爲:1.'remove'只刪除其參數的* first *外觀;和2.你在迭代時改變列表的長度(這是一個壞主意)。 – jonrsharpe

+0

謝謝@jornsharpe,你的觀點二非常重要。但是,如果.remove()僅刪除第一個外觀,爲什麼在錯誤的示例中:「look」將返回「lk」 – chenchenmomo

+0

因爲(僅)其中兩個字母反覆出現是「o''s – jonrsharpe

回答

8

的原因是由@jonrsharpe的評論已經解釋。

我想向你展示一個優化版本,它不工作,並使用列表理解:

def anti_vowel(text): 
    return "".join([x for x in text if x not in "aeiouAEIOU"]) 

print anti_vowel("Hey look Words!") 

輸出:

Hy lk Wrds! 
2

當你迭代它,因爲你改變了長度不應修改的列表,併爲您期望相反,您可以使用yield返回無元音的發電機然後再加入它,它不重複:

def anti_vowel(text): 
    for k in textlist: 
     if k not in"aeiouAEIOU": 
       yield k 

演示:

print ''.join(anti_vowel("Hey look Words!")) 
Hy lk Wrds! 

注意,在這種情況下,你不需要你的字符串列表轉換。

另外,作爲一個更優雅的方式,你可以用re.sub做到這一點:

import re 
def anti_vowel(text): 
    return re.sub(r'[aeiou]+','',text,flags=re.I) 
3

的Python恰巧使用索引遍歷列表時。修改列表是一個壞主意,因爲文檔說不這樣做,並沒有指定行爲。這是發生了什麼

Hey look Words! 
^ 
Hey look Words! 
^ found 'e' so we remove it 
Hy look Words! 
^note that we stepped one step but the removal made us skip 'y' 
... 
Hy look Words! 
    ^found 'o' so we remove it 
Hy lok Words 
    ^again we stepped one step, but the removal made us skip 'o' 
... 
Hy lok Words! 
     ^found 'o' so we remove the first o 
Hy lk Words! 
     ^again we stepped one step, but removing a letter before the cursor make us skip 'r'. 
... 
Hy lk Words! 
     ^consider youself lucky python happens to check the actual length of the list at each iteration - or the cursor would continue into the wilderness. 

吸取的教訓是,當你重複,除非文檔明確說,你可以這樣做不能修改的容器(有時它是在特定的限制,允許)。

相關問題