我试图从列表中仅提取奇数位置的元素。我知道Data.List中有特定的方法,但我是新的,我正在尝试通过重新发明轮子来学习。
到目前为止,我已尝试过这种方法,我正在分支内部方法
manF::[Int]->[Int]
manF []=[]
manF ls=go ls [] 0 where
go [] nl _ = nl
go (x:xs) rez cnt=if cnt `mod`2 ==0 then go xs (x:rez) (cnt+1) else go xs rez (cnt+1)
但我必须在结束时扭转这一结果。
有没有更多的原子然后使用也许来处理null的
因此,如果我移动cons
运算符左侧的 if子句,我可以返回什么而不是null?我已经尝试了Nothing,[]没有成功。
manF::[Int]->[Int]
manF []=[]
manF ls=go ls [] 0 where
go [] nl _ = nl
go (x:xs) rez cnt=if cnt `mod`2 ==0 then x else *(something?!)* : go xs rez (cnt+1)
答案 0 :(得分:7)
但我必须在结束时扭转这一结果。
如果您使用累加器,就像在这里一样,是的,您必须反转结果。如果你正在处理一个"无限列表",这也会导致一个问题,因为在这种情况下,递归永远不会终止,因此你会陷入无限循环(直到你的内存耗尽)。
所以,如果我在cons运算符的左侧移动if子句,我可以返回什么而不是null?
实际上并不是null
(有undefined
,但是我们会将这个值添加到头部),Nothing
也不会这样做,因为那是一个Maybe
类型的数据构造函数。你可以使用空列表,以防你想要终止序列,但你不能填写一些"空"在头脑中。
但实际上你不需要内部方法,也不需要对指数进行评估。您可以使用 pattern 匹配:
manF :: [a] -> [a]
manF (x:_:xs) = x : manF xs
manF [x] = [x]
manF [] = []
请注意,这里的模式是(x:_:xs)
,它是(x:(_:xs))
的紧凑形式,因此我们在这里匹配" cons"以x
为头,尾巴应该是" cons"还有头_
(我们不关心的值),以及尾xs
。通过这样做,我们开发了一种方法,可以在遍历列表时进行两次跳跃。
其他子句是基本情况:对于单例列表,我们返回该单例列表,对于空列表,我们返回空列表。我们可以将最后两个合并为一个子句,如:
manF :: [a] -> [a]
manF (x:_:xs) = x : manF xs
manF l = l
请注意,由于懒惰,如果我们处理一个"无限列表",算法将不会陷入无限循环(当然,鉴于源列表的生成器不会进入无限循环),因此我们可以用它来处理"流"。
另一个优点是我们的整数永远不会遇到溢出(尽管对于偶数奇怪的检查不会产生影响,对于稍微不同的函数,例如每个第三个元素的产生,这个可能导致问题。)
答案 1 :(得分:6)
尝试相互递归。对此的标准演示是相互实施odd
和even
:
odd, even :: Int -> Bool
odd 0 = False
odd n = not (even (n - 1))
even 0 = True
even n = not (odd (n - 1))
对于manF
,您可以写
manF :: [Int] -> [Int]
manF = go_odd where
go_odd [] = []
go_odd (x:xs) = x : go_even xs
go_even [] = []
go_even (x:xs) = go_odd xs