为什么这个索引选择代码不起作用?

时间:2014-10-14 04:40:26

标签: haskell recursion

我试图只返回列表中奇数索引的元素。

我有这个代码,它编译,但它给我一个运行时错误。

这是我的代码:

oddSelect :: [Integer] -> [Integer]
oddSelect []     = []
oddSelect (x:xs) = head (drop 1 (x:xs)) : oddSelect (xs)

3 个答案:

答案 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..]

但是如果你想要自己的递归函数,你仍然需要在某处传递当前索引,或者只有其他方法来删除每一个元素。