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->xmod
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)