2012-06-15 158 views
2

我想遍歷列表檢查列表中的每個字符串的字符。python檢查列表中的字符串?

test = [str(i) for i in range(100)] 

for i in test: 
    if '0' or '4' or '6' or '8' in str(i): 
     test.remove(i) 

我想這將是很好,但是,該列表是在此之後:

[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99] 

凡「2」被刪除,但,在「41」是不是?我注意到它唯一的偶數,但不知道爲什麼。

回答

5

你有兩個問題。首先,總是採用這個if聲明。

if '0' or '4' or '6' or '8' in str(i): 

由於字符串0是一個非零長度的字符串,並且因此True040,因此True。聲明的其餘部分無關緊要。

我希望你真的想測試一下是否每個都是整數的字符串表示形式。正如你現在寫的那樣,你只是測試8是否在字符串中,而且甚至沒有經過測試,因爲表達式在它到達之前評估爲True。像這樣的東西會工作:

if any(x in i for x in '0468'): 

順便說一句,str(i)是多餘的,因爲你的清單已經是一個字符串列表。

另一個問題是,您正在從正在迭代的列表中刪除項目。所以,這裏是發生了什麼:

  • 的第一個項目,0,被刪除的,因爲你的if語句總是服用。
  • 第二項1成爲第一項,因爲您刪除了0
  • for循環繼續執行第二項,現在爲2

換句話說,因爲您刪除0,1從不測試。因此,每個其他項目(所有偶數)都被刪除。

避免這種情況在你的代碼最簡單的方法是遍歷列表的副本:

for i in test[:]: 
11

您的代碼有兩個問題。首先是您在迭代時修改列表。第二個問題是您以錯誤的方式使用or運算符 - if語句中的條件始終爲True

這裏有一個固定的版本:

test = [i for i in range(100) if set("0468").isdisjoint(str(i))] 
0

的問題是在這裏與線:

if '0' or '4' or '6' or '8' in str(i): 

這是不正確。最好是這樣寫:

if any(x in i for x in '0468'): 

第二個問題(如上所述的Sven)是在迭代它的同時修改列表。

最好的解決辦法是:

[i for i in test if not any(x in i for x in '0468')] 
+0

你還在修改'test'在遍歷它。 –

+0

你是對的,我只是試圖接近這個問題。我會修復我的答案 –

+0

謝謝,但即使你願意,這也會是公平的:) –

0
itms = ['0','4','6','8'] 
test = [str(i) for i in range(100) if not any([x in str(i) for x in itms])] 

也許這就是....未經檢驗的,但我認爲它會工作

2

考慮一下:

(Pdb) i=2 
(Pdb) i='2' 
(Pdb) '0' or 'beer' in str(i) 
'0' 
(Pdb) bool('0') 
True 

你明白爲什麼'0' or '4' or '6' or '8' in str(i)並不總是一個布爾值?

現在,考慮你刪除的內容:

>>> l=[str(i) for i in range(10)] 
>>> for i in l: 
... print i 
... print l 
... l.remove(i) 
... 
0 
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] 
2 
['1', '2', '3', '4', '5', '6', '7', '8', '9'] 
4 
['1', '3', '4', '5', '6', '7', '8', '9'] 
6 
['1', '3', '5', '6', '7', '8', '9'] 
8 
['1', '3', '5', '7', '8', '9'] 

當你刪除就地元素,而你遍歷列表中,你縮短了列表,並跳過每下一個值。

Sven has the right pythonic solution,但我覺得更長的解釋可能是值得的。

1

當您執行類似'0' or '4'的操作時,or操作員將驗證第一個參數('0')是否爲false-ish,如果不是false,則返回第一個值。由於'0'是不是假的(它是一個非空字符串,如布爾使用時產生True),它將返回的第一個值和下面的一個甚至不會考慮:如果您重複它

>>> '0' or '4' 
'0' 

,你會得到相同的結果:

>>> '0' or '4' or '6' or '8' 
'0' 

此外,in運營商具有更大的優先級,所以它會每次or前執行:

在 '88' '0' 或 '4' 或 '6' 或 '8' '0'

你想在你的病情做的是驗證任何值是結果:

>>> '0' in str(i) or '4' in str(i) or '6' in str(i) or '8' in str(i) 
True 
>>> i = 17 
>>> '0' in str(i) or '4' in str(i) or '6' in str(i) or '8' in str(i) 
False 

這還不是最完美的解決方案,但它是你的意圖的最好的翻譯。

那麼,什麼是優雅的解決方案?作爲sugested通過@sven,您可以創建尋求字符的集合(more about it):

>>> sought = set("0468") 
>>> sought 
set(['0', '8', '4', '6']) 

,然後創建了一套在你的電話號碼位數:

>>> i = 16 
>>> set(str(i)) 
set(['1', '6']) 

現在,只是看看they are disjoint

>>> i = 16 
>>> sought.isdisjoint(set(str(i))) 
False 
>>> i = 17 
>>> sought.isdisjoint(set(str(i))) 
True 

在這種情況下,如果設定是脫節,那麼要保留它:

>>> found = [] 
>>> for i in range(100): 
...  if sought.isdisjoint(set(str(i))): 
...   found.append(i) 
... 
>>> found 
[1, 2, 3, 5, 7, 9, 11, 12, 13, 15, 17, 19, 21, 22, 23, 25, 27, 29, 31, 32, 33, 35, 37, 39, 51, 52, 53, 55, 57, 59, 71, 72, 73, 75, 77, 79, 91, 92, 93, 95, 97, 99] 

大多數時候,每次你讓自己創造一個for環路濾波迭代器的時候,你真正需要的是一個list comprehension

>>> [i for i in range(100) if sought.isdisjoint(set(str(i)))] 
[1, 2, 3, 5, 7, 9, 11, 12, 13, 15, 17, 19, 21, 22, 23, 25, 27, 29, 31, 32, 33, 35, 37, 39, 51, 52, 53, 55, 57, 59, 71, 72, 73, 75, 77, 79, 91, 92, 93, 95, 97, 99] 

或者,用笨拙,但更多的新手友好構建:

>>> [i for i in range(100) if not ('0' in str(i) or '4' in str(i) or '6' in str(i) or '8' in str(i))] 
[1, 2, 3, 5, 7, 9, 11, 12, 13, 15, 17, 19, 21, 22, 23, 25, 27, 29, 31, 32, 33, 35, 37, 39, 51, 52, 53, 55, 57, 59, 71, 72, 73, 75, 77, 79, 91, 92, 93, 95, 97, 99] 
相關問題