2010-10-13 38 views
2

我想開始學習haskell,並且出現了一個問題。 說,我有一個函數在Haskell中過濾一個列表

countFilter :: (a -> Bool) -> [a] -> ([a], Int) 
countFilter a z = case z of []  -> ([], 0); 
          (x:xs) -> (filter a z , length (filter a z)) 

它返回一個列表,所有的項目,其中適用於某一特定謂詞和名單,這是不相關的長度。

countFilter (<7) [1,2,4,7,11,8,2]將輸出([1,2,4,2], 4)

如何創建這樣的輸出:([7,11,8], 4)使用相同的謂詞(< 7)?

回答

5

如果我正確理解你的問題,你想返回不作爲作爲對的第一個元素與謂詞(< 7)匹配的所有元素。

在這種情況下,您可以簡單地使用not函數來翻轉生成的布爾值。
I.e.創建使用功能組成一個新的謂詞(\x -> not (oldPred x)),或:(not . oldPred)

countFilter :: (a -> Bool) -> [a] -> ([a], Int) 
countFilter f xs = (filter (not . f) xs, length (filter f xs)) 

注意兩個filterlength可以處理空列表,這樣你就不需要自己寫case


或者,您可以使用partition函數來創建兩個列表,這樣你就不會過濾列表兩次:

import Data.List 

countFilter :: (a -> Bool) -> [a] -> ([a], Int) 
countFilter f xs = let (ys, zs) = partition (not . f) xs 
        in (ys, length zs) 

這或許可以創建一個更有效的版本,不使用length,但我將其留作練習:-)

+0

優秀!我只是沒有注意到參考文獻中的「不」)試圖實現「否定」,而不是...我還沒有把它分區和輸入想法,但我會回到你的答案,因爲我將繼續在我的哈斯克爾路上。) – bogatyrjov 2010-10-13 12:29:15

相關問題