Jes*_*sse 3 haskell filtering predicate list filter
我将此代码输入ghci
Prelude> filter snd [('a',True),('b',True),('c',False),('d',True)]
Run Code Online (Sandbox Code Playgroud)
为什么返回
[('a',True),('b',True),('d',True)]
Run Code Online (Sandbox Code Playgroud)
而不是
[('a',True),('c',False),('d',True)]
Run Code Online (Sandbox Code Playgroud)
snd函数返回第二个项目,那么为什么不filter snd过滤第二个项目呢?
您希望filter从该表达式的口语意义上 “过滤”出列表中的元素,从而filter snd 删除第二项。
那不是它的工作原理
如果您是对的,请filter snd [1,2,3]评估为[1,3]。相反,它不会像snd对元组(而不是数字)那样进行类型检查。
那么它是怎样工作的?
filter f [item1, item2, ...]返回所有列表itemS表示这f item是True
例如,filter even [1,2,3,4]返回[2,4]
作为snd ('b', True)对的评估True,您的示例filter中将包括(b, True)结果。同样,(c, False)将省略
简而言之:filter snd保留2元组,其中元组的第二项是True。
filter :: (a -> Bool) -> [a] -> [a]将将类型的元素映射a到的函数作为参数Bool。如果Bool是True,它将在结果中保留原始列表的元素,否则该元素将不属于结果的一部分。
filter因此,过滤器的elementwise:它并没有考虑到列表中的下一个或前一个元素(一个或多个)。它只是检查元素上的谓词是否满足。
由于您在这里有一个2元组的列表,其中每个元组的第二个项目是a Bool,因此snd :: (a, b) -> b会将每个元素映射到第二个元素,因此保留2元组,其中2个元组的第二个项目是True。filter snd因此filter snd :: [(a, Bool)] -> [(a, Bool)],最通用的类型是,因为2元组的第二项应为Bool。
因此,这意味着filter snd确实将进行如下过滤:
Prelude> filter snd [('a',True),('b',True),('c',False),('d',True)]
[('a',True),('b',True),('d',True)]
Run Code Online (Sandbox Code Playgroud)
我们可以使用显式递归来过滤掉第二个元素,例如:
filterAtEven :: [a] -> [a]
filterAtEven [] = []
filterAtEven (x:xs) = x : filterAtOdd xs
filterAtOdd :: [a] -> [a]
filterAtOdd [] = []
filterAtOdd (_:xs) = filterAtEven xs
Run Code Online (Sandbox Code Playgroud)
例如:
Prelude> filterAtEven [('a',True),('b',True),('c',False),('d',True)]
[('a',True),('c',False)]
Prelude> filterAtOdd [('a',True),('b',True),('c',False),('d',True)]
[('b',True),('d',True)]
Run Code Online (Sandbox Code Playgroud)
或者,如果您要删除特定的索引,我们可以使用deleteAt :: Int -> [a] -> [a]该ilist软件包:
Prelude> import Data.List.Index
Prelude Data.List.Index> deleteAt 2 [('a',True),('b',True),('c',False),('d',True)]
[('a',True),('b',True),('d',True)]
Run Code Online (Sandbox Code Playgroud)
或者我们可以自己实现:
deleteAt :: Int -> [a] -> [a]
deleteAt i | i < 0 = id
| otherwise = go i
where go _ [] = []
go 0 (_:xs) = xs
go n (x:xs) = x : go (n-1) xs
Run Code Online (Sandbox Code Playgroud)