我是哈斯克尔新来的。我试图使用递归编写一个函数,给定两个列表(它们需要相同的类型),交错它们的元素(在第一个列表和第二个列表之间交替使用元素)。当其中一个列表中没有更多的元素时,它就停止了,结果就是实现了那么远的列表。
interChange :: [a] -> [b] ->[(a,b)]
interChange _ [] = []
interChange [] _ = []
interChange (x:xs) (y:ys) = (x,y) : interChange xs ys我的输出示例:
interChange [1,2,3] [4,5,6]
[(1,4),(2,5),(3,6)]所需输出的示例如下:
interChange [1,2,3] [4,5,6]
[1,4,2,5,3,6]谢谢你的帮忙
发布于 2017-01-22 15:20:38
你的interChange和前奏曲的zip是一样的。
ghci> zip [1,2,3] ["wibble", "wobble", "wubble"]
[(1,"wibble"),(2,"wobble"),(3,"wubble")]要编写指定的函数,实际上需要一对相同类型的列表。我们输出一个特定类型的列表,所以该列表中的所有元素也必须具有该类型。
interleave :: [a] -> [a] -> [a]您可以以递归的方式实现这一点,方法是传递一个Bool,指示您应该从哪个列表中获取下一个元素:
interleave = go True
where go _ [] ys = ys
go _ xs [] = xs
go True (x:xs) ys = x : go False xs ys
go False xs (y:ys) = y : go True xs ys在go的最后两个子句之间计算ping-pongs,直到其中一个输入列表为空为止,因此我们只返回另一个输入列表的其余部分。(如果希望它的行为更像zip,可以通过返回[]而不是xs或ys来截断输出。)
但我总是建议在可能的情况下避免递归到更高级别的程序。我们可以将这个函数写成一个管道:
zip对输入列表的元素map (\(x, y) -> [x, y])concat将结果列表平平。代码看起来如下:
interleave xs ys = concat $ map (\(x, y) -> [x, y]) $ zip xs ys我发现这段代码比递归代码更容易理解,递归代码要求您对控制流进行推理--这只是一系列高级指令。
顺便说一句,您可以通过将中间map拖到concat或zip中来删除它。
interleave xs ys = concatMap (\(x, y) -> [x, y]) $ zip xs ys
interleave xs ys = concat $ zipWith (\(x, y) -> [x, y]) xs ys发布于 2017-01-22 15:36:43
当interChange被两个非空列表( (x:xs)和(y:ys) )调用时,输出应该是以x和y开始的列表,然后是更多的东西。所以你应该写点什么
interChange (x:xs) (y:ys) = x : y : ...https://stackoverflow.com/questions/41792586
复制相似问题