dropnth' :: [a] -> Int -> [a]
dropnth' xs n = foldl (\a b -> if (last a) == xs!!n then a else b ++ []) [head xs] xs
我试图解决这个问题"删除列表中的每个第n个元素"使用foldl的问题,但我收到了错误。我怎么能这样做?
错误:
答案 0 :(得分: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]
这样的签名类型会更好。