我试图只返回列表中奇数索引的元素。
我有这个代码,它编译,但它给我一个运行时错误。
这是我的代码:
oddSelect :: [Integer] -> [Integer]
oddSelect [] = []
oddSelect (x:xs) = head (drop 1 (x:xs)) : oddSelect (xs)
答案 0 :(得分:3)
如果你想使用递归:
evenSelect :: [a] -> [a]
evenSelect [] = []
evenSelect [x] = [x]
evenSelect (x:_:xs) = x : evenSelect xs
我更喜欢的另一个解决方案:
import Data.List.Split
evenSelect :: [a] -> [a]
evenSelect = map head . chunksOf 2
答案 1 :(得分:1)
就个人而言,我认为这不是一个好的解决方案。大多数情况下,我通常会谨慎使用head
。
我个人做的是用索引压缩元素,然后删除所有偶数(filter odd
)然后最终删除索引(map snd
)
oddSelect :: [Integer] -> [Integer]
oddSelect l = map snd $ filter (\(idx,value) -> odd idx) (zip [1..] l)
至于你的代码, 这句话很好
oddSelect [] =[]
但第二个需要一些工作。我已经为你重写了它:
oddSelect (x:xs) =x:oddSelect (drop 1 xs)
x已经是列表的第一个元素(不是列表本身),因此它可以添加到新列表的头部。现在,您希望以递归方式再次调用您的函数,但现在您想要剪切列表REST的第一个元素,因为它是偶数 - 因此您要调用drop 1 xs
而不是drop 1 (x:xs)
相当于只使用xs
答案 2 :(得分:0)
drop 1 (x:xs)
实际上与xs
相同。如果xs
为空,则head
必须失败。实际上,即使您修复了那部分,它仍然无法工作,因为此时您正在尝试无条件地删除第一个元素并继续递归,这将始终返回一个空列表。
简单的方法是:
oddSelect = map snd . filter (odd . fst) . zip [1..]
但是如果你想要自己的递归函数,你仍然需要在某处传递当前索引,或者只有其他方法来删除每一个元素。