【问题标题】:How can I drop nth element of a list using foldl?如何使用 foldl 删除列表的第 n 个元素?
【发布时间】:2017-12-23 17:39:52
【问题描述】:
dropnth' :: [a] -> Int -> [a]
dropnth' xs n = foldl (\a b -> if (last a) == xs!!n then a else b ++ []) [head xs] xs

我试图使用 foldl 解决这个“删除列表的每个第 n 个元素”的问题,但我遇到了一个错误。我该怎么做?

错误:

【问题讨论】:

  • “我遇到错误”不是很有帮助,请在您的帖子中发布完整的错误消息,而不是图片。
  • 尽可能避免head,tail,!! 总是更好,因为这些是危险的部分。
  • 你真的不应该为此使用foldl。保证你得到的代码效率低于应有的效率和懒惰。 foldr 你可以做得更好,但你必须要聪明一点。

标签: haskell higher-order-functions fold


【解决方案1】:

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 -&gt; [a] -&gt; [a] 之类的签名会更好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多