List 取出Haskell中列表中某个元素的最后一个匹配项

List 取出Haskell中列表中某个元素的最后一个匹配项,list,haskell,recursion,List,Haskell,Recursion,我在编写这个函数时遇到了问题,它接受谓词和整数列表,然后消除满足列表中谓词的整数的最后一次出现。我能够使用下面的函数取出列表中第一个出现的谓词: fun :: (Int -> Bool) -> [Int] -> [Int] fun check (s:ss) |check s = ss |otherwise = s : fun check ss 我需要的帮助是如何修改此函数以去掉整数的最后一个匹配项,而不是第一个匹配项。例如,fun((由于一些缩进问题,我无法使用where

我在编写这个函数时遇到了问题,它接受谓词和整数列表,然后消除满足列表中谓词的整数的最后一次出现。我能够使用下面的函数取出列表中第一个出现的谓词:

fun :: (Int -> Bool) -> [Int] -> [Int]
fun check (s:ss)
 |check s = ss
 |otherwise = s : fun check ss
我需要的帮助是如何修改此函数以去掉整数的最后一个匹配项,而不是第一个匹配项。例如,
fun((由于一些缩进问题,我无法使用
where

go
收集谓词不包含在差异列表中的元素,并在找到满足谓词元素的新元素后将此列表添加到结果的前面。
break p xs
上的模式匹配确保差异列表始终以满足谓词的元素开始,如果它是最后

适用于无限列表:

main = do
    print $ removeLast (< 2) [3,4,1,5,0,-3,9]        -- [3,4,1,5,0,9]
    print $ removeLast (== 2) [1,3]                  -- [1,3]
    print $ take 10 $ removeLast (< 2) (cycle [1,3]) -- [1,3,1,3,1,3,1,3,1,3]
这个怎么样:

fun :: (Num a) => (a -> Bool) -> [a] -> [a]
fun check (s:ss)
    |check s = ss
    |otherwise = s : fun check ss
然后,像这样应用您的
fun
功能:

reverse $ fun (\ x -> x `mod` 3 == 0) (reverse [1..10])

HTH

如果你想玩得开心,试试这个版本

removeLast :: (a -> Bool) -> [a] -> [a]
removeLast p = fst . foldr go ([], False) where
  go x ~(r, more)
    | p x = (if more then x : r else r, True)
    | otherwise = (x : r, more)
这似乎是尽可能的懒惰,而且它很快就说到了点子上。它可以通过一些努力更懒地生成列表脊椎,但它最大限度地懒地生成列表元素


经过深思熟虑,我意识到在这种情况下,懒惰的不同方面之间存在着某种紧张关系

removeLast p (x : xs)
有两种方法可以尝试确定是生成
[]
还是
(:)
构造函数

  • 我们可以检查
    xs
    ;如果
    xs
    不是
    []
    ,那么我们可以生成
    (:)

  • 我们可以检查
    px
    。如果
    px
    False
    ,那么我们可以生成
    (:)


  • 这些是唯一的方法,它们的严格程度是无法相比的。唯一的“最大限度的懒惰”方法是使用并行性来尝试这两种方法,这不是最实用的方法。

    将其写成
    反向。removeFirstOccurance谓词。反向
    ?我尝试过反向,我试图将其保持在同一个函数中。@user3237465-你能解释一下你的意思吗?@ErikR,
    反向
    总是遍历整个列表,因此您的函数不能处理无限列表。请参阅我的答案以获得替代方法。@t-Bird接近复制接近逐字复制,您自己在3小时前询问过。只需将
    c1==c2
    替换为
    PS
    或其他内容。
    接受10$removeLast(\x->rem x 3==0)[1..]
    使用您的版本
    removeLast p=reverse.fun p.reverse
    会导致内存不足。是的,确实如此。这里的问题是去掉最后一个元素(满足谓词)从一个无限的列表……这对我来说没有多大意义…例如,你如何从一个无限的随机数列表中取出具有%3==0的最后一个数字(尽管列表在我的答案中被排序,让我们考虑一个随机数的一般列表)?我和DFuuER的版本(另外两个答案)给出[ 1…10 ]。在这个例子中。@user3237465:BTW即使我输入了这个注释,你的版本仍然在打印数字。你试过把这一行放在你的main中吗?print$removeLast(\x->x
    mod
    3==0)[1..]当然,这个列表是无限的。关键是,对于任何一个数字,你都知道它不是最后一个满足
    rem x 3==0
    ,因此你可以生成这个数字。你的版本不生成,我的版本生成。如果你尝试打印
    [1..]
    ,你也会得到一个无限循环。这应该是公认的答案。一个小建议:
    [x | more]++r
    @user3237465,确实非常紧凑,但不是我的风格。不过这是一个惊喜!
    removeLast :: (a -> Bool) -> [a] -> [a]
    removeLast p = fst . foldr go ([], False) where
      go x ~(r, more)
        | p x = (if more then x : r else r, True)
        | otherwise = (x : r, more)
    
    removeLast p (x : xs)