从嵌套列表中过滤元素

4
我很难理解函数式编程背后的逻辑。所以,这应该是一件相当简单但对我来说不起作用的事情。 我试图做的是: 一个带参数列表的函数,而列表是这样的:[[1,2,3], [5,7,8,12,34], [2,4,6,8]] 首先,我应该删除小于6的值,然后删除所有元素少于2个的列表。我的代码如下:
f11 :: [[Int]] -> [[Int]]
f11 xs = ( filter (\s -> if a <= 6 a then True else False )) (map (filter (\x -> length x <= 2)) xs)

小的风格建议:您可以避免使用反模式 if condition then True else False,它可以简化为 condition。例如,可以编写 filter (\x -> x>=6) [1..10] - chi
4个回答

1
您误解了,应该这样查看:

f11 :: [[Int]] -> [[Int]]
f11  =  (filter \x-> length x < 2) . (map (filter \x -> x > 6))

2
我认为使用无点谓词更好看,但我想有些人可能会不同意:f11 = filter ((< 2) . length) . map (filter (>= 6)) - amalloy
@amalloy 真不错。更好的是 - Netwave
谢谢。我只需要检查一下那些“点”是做什么的 =) - Pelin
@Pelin,这些点表示函数组合,就像将两个函数的行为合并成一个。 - Netwave
太好了!感谢 @Daniel Sanchez 的解释。 - Pelin
@Pelin,仅为完整性,((< 2) . length) xs == (< 2) (length xs) == length xs < 2 - Will Ness

1

这是一个品味问题,但为了易读性,您可能需要使用中间变量:

f11 :: [[Int]] -> [[Int]]
f11 xs = 
    let 
        less6Cleared = map (filter (\x -> x >= 6)) xs
    in  
        filter (\x -> length(x) >= 2) less6Cleared                       

这段话的意思是,less6Cleared 是一个列表的列表,其中所有元素都已经清除了少于 6 的内容。现在你需要对 less6Cleared 应用一个过滤器。

1

由于列表实现了Monad,因此您还可以使用do表示法。

f11 xss = do
    xs <- xss
    let ys = [x | x <- xs, x >= 6]
    guard (length ys <= 2)
    return ys

do 表示对 列表 进行的操作基本上是一个 foreach 循环。我们从 xss 中提取每个元素 xs,然后通过列表推导式将其传递,过滤出小于6的元素,并将结果命名为ys。然后,guard 过滤掉长度超过2的 ys


0
如果你想要在点自由风格和部分函数应用方面发挥创意...
f11 :: [[Int]] -> [[Int]]
f11 = (filter $ (>= 2) . length) . (map $ filter (>= 6))

...但对于那些不习惯它的人来说,它可能不会更清晰。

同时,我将您的“小于”要求解释为严格要求,因此值为6的条目未被删除,长度为2的列表也未被删除。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接