从列表中提取元素并返回元素,以及元组中其余列表的有效方法是什么?

时间:2013-03-10 15:38:41

标签: haskell

这似乎是一种非常常见的操作,但由于某些原因我无法在hoogle中找到它。无论哪种方式,这是一个有趣的思想练习。我天真的实施:

pluckL :: [a] -> Int -> Maybe ( a, [a] )
pluckL xs idx = if idx < length xs then Just $ pluck' xs idx else Nothing
where
    pluck' l n = let subl = drop n l in ( head subl, rest l n ++ tail subl )
    rest   l n = reverse $ drop ( length l - n ) $ reverse l

我的主要抱怨是我在列表中翻了太多次,所以我正在寻找一种创造性的方法,你可以在其中遍历列表并生成元组。

3 个答案:

答案 0 :(得分:7)

永远不会有一种有效的方法。但至少可以采用一种漂亮的方式:

pluckL xs i = case splitAt i xs of
    (b, v:e) -> Just (v, b ++ e)
    _ -> Nothing

答案 1 :(得分:1)

如果您使用累加器,则可以减少列表中reverse次操作的次数:

pluckL :: [a] -> Int -> Maybe (a, [a])
pluckL xs idx = pluck xs idx [] where
    pluck (x:xs) 0 acc = Just $ ( x, (reverse acc) ++ xs )
    pluck (x:xs) i acc = pluck xs (i-1) (x:acc)
    pluck [] i acc = Nothing

答案 2 :(得分:1)

您可以使用 elem 检查elem是否在列表中,然后根据结果返回Nothing或使用 delete x 从列表中删除x ,例如,

pluckL :: Eq a => [a] -> a -> Maybe (a, [a]) 
pluckL xs0 x =  
    if (x `elem` xs0) 
    then Just (x, xs) 
    else Nothing
        where xs = delete x xs0