获取列表中的下一个元素

时间:2014-05-26 08:37:44

标签: haskell

是否有更简单的方法(可能是标准功能):

(如果列表包含元素,则结果是该元素的下一个元素 列表;如果元素是列表的最后一个元素,则结果是第一个元素 的清单。 "特殊情况":如果列表为空,则结果为Nothing。如果是清单 不包含元素,结果是列表的第一个元素。)

import Data.List

next :: Eq a => Maybe a -> [a] -> Maybe a
next _ [] = Nothing
next Nothing (x:_) = Just x
next (Just x) list = Just $ list !! index
    where index =
        case elemIndex x list of
        Nothing -> 0
        Just xIndex ->
            if xIndex + 1 == length list
            then 0
            else xIndex + 1

3 个答案:

答案 0 :(得分:7)

让我们调用元素e和列表xs。如果将开头的所有元素与e不等于dropWhile (/= e),则会更容易。之后,您可以专注于两种情况,我们将始终返回一个值:

  1. 其余列表至少包含两个元素。我们可以在(_:y:_)上进行模式匹配,以便在e之后获取元素并返回y
  2. 其余列表只包含一个元素或为空。在这种情况下,我们可以返回原始的第一个元素。
  3. 总的来说,我们得到了

    next :: Eq a => Maybe a -> [a] -> Maybe a
    next _ []             = Nothing
    next Nothing    (x:_) = Just x
    next (Just e) l@(x:_) = Just $ case dropWhile (/= e) l of
                              (_:y:_) -> y
                              _       -> x
    

答案 1 :(得分:2)

首先,我要更改您的功能的签名,通常您不会定义仅适用于Maybe的功能。

所以我介绍一个函数,它返回给定元素之后的列表部分。

following :: (Eq a) => a -> [a] -> [a]
following _ [] = []
following x (y:l) = if x==y then l else following x l

然后我定义下一个返回'跟随x l'的第一个元素。或列表的第一个元素。

next :: (Eq a) => [a] -> a -> Maybe a
next [] _ = Nothing
next l x = if f == [] then Just(head l) else Just(head f)
    where f = following x l

现在你可以使用' next'这样:

> l = 2 : 5 : 6 : 1 : []
> next l 5
6
> next l 7
2

如果你想打电话给下一个也许你可以使用一个可能是一个Monade的事实。

> Just 5 >>= next l
Just 6

注意:我交换了next的参数,以便更容易按照他的方式调用它。

答案 2 :(得分:1)

通过使用尾部压缩列表,我们获得了元素及其后继者的关联列表:

> lookup 1 $ (zip <*> tail) [1,2,3,4]
Just 2

> lookup 4 $ (zip <*> tail) [1,2,3,4]
Nothing

这也很懒惰:

> lookup 4 $ (zip <*> tail) [1..]
Just 5