如何使用foldl删除列表的第n个元素?

问题描述 投票:-3回答:1
dropnth' :: [a] -> Int -> [a]
dropnth' xs n = foldl (\a b -> if (last a) == xs!!n then a else b ++ []) [head xs] xs

我试图使用foldl解决这个问题“删除列表中每个第n个元素”的问题,但是我收到了一个错误。我怎样才能做到这一点?

错误:

haskell higher-order-functions fold
1个回答
4
投票

a可能是你已经决定不放弃的元素。然后你应该决定是否放弃,而不是a的最后一个元素,而是xs中的下一个元素,大概是b

b ++ []大概是为了表示你决定不放弃元素b,而是将其添加到列表a。这实际上是写a ++ [b]

这允许我编写这段代码,至少编译:

dropnth' :: Eq a => [a] -> Int -> [a]
dropnth' xs n = foldl (\a b -> if b == xs!!n then a else a ++ [b]) [head xs] xs

xs!!n找到了xs的第n个元素,并且与之相比,将确定某个值是否等于那个值,而不是某个位置。请注意Eq a,它告诉我们正在比较列表值。 foldl必须从某个地方获取参赛作品的位置,例如来自zip [0..]

dropnth' :: [a] -> Int -> [a]
dropnth' xs n = foldl (\a (i, b) -> if mod i n == 0 then a else a ++ [b]) [head xs] (zip [0..] xs)

将元素添加到列表末尾必须重建整个列表。从最终构建列表会更有效率。但在这种情况下,我们甚至可以为我们的用例使用更专业的列表操作。

dropnth' :: [a] -> Int -> [a]
dropnth' xs n = [b | (i, b) <- zip [0..] xs, mod i n > 0]

请注意,我们现在也删除了初始元素。也许这就是你想要的?或者你可以zip[1..]而不是将所有的十字准线向左移动。

通常,像Int -> [a] -> [a]这样的类型签名组合得更好。

© www.soinside.com 2019 - 2024. All rights reserved.