这似乎是一种非常常见的操作,但由于某些原因我无法在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
我的主要抱怨是我在列表中翻了太多次,所以我正在寻找一种创造性的方法,你可以在其中遍历列表并生成元组。
答案 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