Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 查找列表中元素的前一个元素(Haskell)_List_Haskell - Fatal编程技术网

List 查找列表中元素的前一个元素(Haskell)

List 查找列表中元素的前一个元素(Haskell),list,haskell,List,Haskell,我想返回列表中元素的前一个元素。我打算获取parameter的索引,并使用它来弃用list,使parameter成为最后一个元素,然后将其反转,并获取反转list的第二个元素。 我得到错误:typeelemIndex是Maybe Int,而take函数需要Int。我想用简单的递归来修复它或编写代码 是否有使用递归的较短代码 precedingElement :: Eq a => a -> [a] -> Maybe a precedingElement elt lst |

我想返回列表中元素的前一个元素。我打算获取parameter的索引,并使用它来弃用list,使parameter成为最后一个元素,然后将其反转,并获取反转list的第二个元素。 我得到错误:type
elemIndex
Maybe Int
,而
take
函数需要
Int
。我想用简单的递归来修复它或编写代码 是否有使用递归的较短代码

precedingElement :: Eq a => a -> [a] -> Maybe a
precedingElement elt lst    | lst == [] = error "List is empty"
                            | elt `notElem` lst = Nothing
                            | otherwise = Just x where x = snd (reverse (take (elt `elemIndex` lst) lst))

为了返回给定元素的前一个元素,可以使用一些模式匹配和递归:

precedingElement _ [] = Nothing
precedingElement _ [x] = Nothing
precedingElement elt (x:y:rest)
    | y == elt = Just x
    | otherwise = precedingElement elt (y:rest)

因为我是一个超级粉丝,我可能会写一些类似的东西

lastBefore :: (a -> Bool) -> [a] -> Maybe a
lastBefore p xs = foldr go (`seq` Nothing) xs Nothing
  where
    go x r (Just prev) | p x = Just prev
    go x r _ = r (Just x)

但我必须检查GHC是否如我所愿对其进行了优化。

我最喜欢的未被重视的实用程序之一对于此类问题非常方便。让我有反向列表,这样我就不需要反向思考了

data Bwd x = B0 | Bwd x :< x  -- rightmost is nearest
知道我的老歌的人会把
ListContext
看作是
[]
的派生词

焦点中的一个元素(你的手指在珠子上)是

还有一个有用的操作,它用上下文装饰每个列表元素,使其成为焦点

focus :: [x] -> [ListFocus x]
focus = go B0 where
  go xz [] = []
  go xz (x : xs) = ((xz, xs), x) : go (xz :< x) xs
计算
xs
x
左侧的所有值
p
。如你所见


(顺便说一句,这个
focus
操作并非无中生有。它源于列表数据类型的差异结构。(它被称为
picks
)更详细地讲述了列表故事,并发展了数据类型通用故事。)

这方面的标准解决方案是使用压缩:

import Data.List (find)

preceding :: (a -> Bool) -> [a] -> Maybe a
preceding f xs = fmap snd . find (f . fst) $ zip (drop 1 xs) xs

小nit:这会导致一个元素列表崩溃和烧毁。:)@亚历克:哎呀。谢谢你的帮助。增加了另一种情况。考虑<代码>先行元素elt xs=查找elt(zip(下标1×x)xs)< /代码>。如果你先放<代码>(x:y:REST)第一个例子,第二个(和最后一个)情况可以简单地是<代码>先行元素=没有< /代码>。我已经回答了标题中的问题。然而,你问题的其余部分很难理解。我不确定“我打算获取参数的索引并使用它来弃用列表,使参数成为最后一个元素,然后将其反转并获取反转列表的第二个元素”是什么意思。我建议您将其分解成小块,并分别为每一块编写代码。当你构建你的代码时,你最终会得到一个完整的解决方案。我真的开始喜欢这些了。不过有一个问题:为什么
(`seq`Nothing)
而不是
(const Nothing)
?请注意
lastBefore(=0)[0,1,0,2,3]
将返回
只有1
,这与code学徒的答案不同。不过,将其中一个答案更改为另一个答案的行为是微不足道的。(尽管如此,我还不喜欢foldr的四参数模式——即使我有时也会使用它。)@Alec,这也许没关系,但我已经了解到,让严格性非常一致可以帮助优化器。在那里使用
seq
可以确保始终需要生产的
Maybe
。这可能很重要,也可能不重要,但它让我感觉更好。
focus :: [x] -> [ListFocus x]
focus = go B0 where
  go xz [] = []
  go xz (x : xs) = ((xz, xs), x) : go (xz :< x) xs
focus [1,2,3] = [((B0,[2,3]),1), ((B0 :< 1,[3]),2), ((B0 :< 1 :< 2,[]),3)]
[p | ((_ :< p,_),q) <- focus xs, q == x]
import Data.List (find)

preceding :: (a -> Bool) -> [a] -> Maybe a
preceding f xs = fmap snd . find (f . fst) $ zip (drop 1 xs) xs