2010-11-26 23 views
1

我試圖篩選列表,這裏是代碼:過濾Python列表時發生意外輸出:我在做什麼錯?

test=['aaa','bbb','ccc','ddd','footer','header'] 

def rm_hf(x): return x != 'footer' 

filter(rm_hf,test) 

結果:

>>>['aaa','bbb','ccc','ddd','header'] 

,預計結果是,在列表中找到「腳註」並將其刪除。

現在我想刪除這兩個「頭」和「尾」,所以我這樣做:在

test2=['aaa','bbb','ccc','ddd','footer','header'] 

def rm_hf2(x): return x != 'footer' or x != 'header' 

filter(rm_hf2,test2) 

結果:

>>>['aaa','bbb','ccc','ddd','footer','header'] 

現在很奇怪,它只是給了兩個「頁腳','標題'而不是過濾它們?

我做錯了什麼?我認爲我的邏輯是正確的...

+4

,而不是或!!!!! – 2010-11-26 01:05:55

+3

-1:瑣碎的邏輯問題與「怪異行爲」和「Python中的bug」混淆起來。這總是邏輯。測試`rm_hf2`有多難? – 2010-11-26 01:47:24

+0

嗯,我只是問清楚問題,你只是投我我而不是糾正我,哇,什麼專家大聲笑。我不能停止笑。我反正不在乎這裏的選票,所以喜歡投票給我:) – 2010-11-26 02:08:53

回答

7

你的邏輯是正確的,因爲你像人一樣思考。你的電腦沒有。他從你的列表中讀取每一個元素,然後絆倒「頁腳」。 「腳註與腳註不同嗎?」他說。 「不!這是相同的字符串!它被評估爲假,讓我們看看下一個條件」。 「頁腳與頁眉不同?是!」因此條件爲False or True,顯然評估爲真。

你想要一個and,而不是一個or

def rm_hf2(x): return x != 'footer' and x != 'header' 

你也可以使用一個元組和in關鍵字,這是更具可讀性:

def rm_hf2(x): return x not in ('footer', 'header') 

重要的是,你明白什麼是真正儘管如此,繼續使用「和」和「或」。說實話:如果某件事不像你想象的那樣工作,那麼問題很可能出現在你自己的代碼中,而不是Python語言本身。

2

什麼其他人說,加:

當你有,你要排除的幾個項目,使用set代替and個鏈或tuple

# do once 
blacklist = set(['header', 'footer']) 

# as needed 
filter(lambda x: x not in blacklist, some_iterable) 

理由:展望通過tuple需要的時間與找到的項目的位置成比例;失敗與最後一項相同。查找一個集合中的項目對於所有項目和失敗都需要相同的時間。集合通常會贏得大量的物品。這一切都取決於每個項目將被搜索的概率,以及失敗的概率是多少。如果有幾件物品的可能性很高(它們應該放在元組的前面)並且出現故障的可能性很小,那麼元組可以贏得大量的收藏。

1

你也可以使用列表理解而不是過濾器。

test = ['aaa','bbb','ccc','ddd','footer','header'] 
filtered_test = [x for x in test if x not in ('footer', 'header')] 

或發電機表達式(取決於你的需求)

test = ['aaa','bbb','ccc','ddd','footer','header'] 
filtered_test = (x for x in test if x not in ('footer', 'header')) 
4

my logic is correct

其實,不,沒有,在其他的答案突出。

一個很整齊的方式來實現期望的結果是使用list comprehensions

test = ['aaa', 'bbb', 'ccc', 'ddd', 'footer', 'header'] 
undesirable = ['footer', 'header'] 
[_ for _ in test if _ not in undesirable] 

the documentation

Note that filter(function, iterable) is equivalent to [item for item in iterable if function(item)] if function is not None and [item for item in iterable if item] if function is None .

這就是說,沒有時間像現在刷你的Boolean logic

如果你要單元測試你的代碼,你會很快發現你的第二個過濾函數沒有達到你所期望的。這裏是一個簡單的例子:

$ cat 4281875.py 
#!/usr/bin/env python 

import unittest 

def rm_hf2(x): return x != 'footer' or x != 'header' 

class test_rm_hft(unittest.TestCase): 

    def test_aaa_is_not_filtered(self): 
     self.assertTrue(rm_hf2('aaa')) 

    def test_footer_is_filtered_out(self): 
     self.assertFalse(rm_hf2('footer')) 


if __name__ == '__main__': 
    unittest.main() 


$ ./4281875.py 
.F 
====================================================================== 
FAIL: test_footer_is_filtered_out (__main__.test_rm_hft) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "./4281875.py", line 13, in test_footer_is_filtered_out 
    self.assertFalse(rm_hf2('footer')) 
AssertionError 

---------------------------------------------------------------------- 
Ran 2 tests in 0.000s 

FAILED (failures=1) 
相關問題