【问题标题】:How to filter list elements in Haskell based on previous value in the list?如何根据列表中的先前值过滤 Haskell 中的列表元素?
【发布时间】:2020-02-29 09:35:29
【问题描述】:

我正在 Haskell 中创建一个函数,该函数根据列表中的前一个元素过滤列表中的数字。

例子

前面的数字是2的倍数

myFunction [1, 2, 5, 6, 3]
# expected output:
[5,3]

我知道如何应用filter,但到目前为止我已经看到过滤器一次只接受一个参数。

我尝试使用 scanl1foldl1map,但我是 Haskell 的新手,但我无法这样做;有什么线索吗?

【问题讨论】:

    标签: list haskell filter functional-programming


    【解决方案1】:

    编辑

    应该是:

    myFunction []       =  []
    myFunction [x]      =  []
    myFunction [x,y]    =  if (x `mod` 2) == 0 then [y] else []
    myFunction (x:y:xs) =  if (x `mod` 2) == 0 
                          then y : (myFunction xs)
                          else myFunction (y:xs)
    

    因为对于输入:

    myFuntion [1, 2, 5, 6, 3]
    

    正确的输出应该是:

    [5,3]
    

    【讨论】:

    • 我对过滤器有点迷茫,我想我必须结合使用它来一次迭代两个元素,我仍然在命令世界中,非常感谢,我需要多学习一点才能理解这个例子和 (x:y:xs) 符号:)
    • @FrederickÁlvarez 当我需要抛出每次消耗两个元素的列表时,我会使用这种模式匹配,您还可以阅读有关 fold1 的更多信息,有时也很有用
    • @FrederickÁlvarez let xs = [1, 2, 5, 6, 3] in [ y | (x,y) <- zip xs (drop 1 xs), even x] 也是一种可能。我现在看到另一个答案已经使用了zip 函数,但是使用列表推导,代码可以更清晰(尽管您确实要求filter)。
    【解决方案2】:

    如果您更喜欢使用库函数,对于这种情况有一个已知的技巧,即使用自己的尾部压缩输入,即初始列表减去其第一个元素。

     λ> 
     λ> inls = [1, 2, 5, 6, 3]
     λ> 
     λ> let pairs = zip (tail inls) inls
     λ> pairs
     [(2,1),(5,2),(6,5),(3,6)]
     λ> 
    

    然后生成的对列表是mapfilter 的简单目标。 如:

    λ> let myFunction ls = let pairs = zip (tail ls) ls  in  map fst $ filter (even . snd) pairs
    λ> 
    λ> ls
     [1,2,5,6,3]
    λ> 
    λ> myFunction ls
    [5,3]
    λ> 
    

    【讨论】:

      猜你喜欢
      • 2021-12-29
      • 1970-01-01
      • 1970-01-01
      • 2017-08-12
      • 2019-10-22
      • 1970-01-01
      • 2012-06-20
      • 2018-07-14
      相关资源
      最近更新 更多