2017-01-22 51 views
2

我是Haskell中的新成员。我试图用递归写一个函数,给定两个列表(它们需要是相同类型的),交织它们的元素(将元素在第一个和第二个列表之间交替)。当其中一个列表中没有更多元素时,它会停止并且结果就是达到的列表。我输出的如何从两个列表中创建列表以及来自这些列表的元素

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] 

感谢您的帮助

回答

3

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最后两个分句,直到之间的平pongs任何一个输入列表都是空的,因此我们只返回另一个列表的其余部分。 (如果你想让它更象zip你可以有它通过返回[]而不是xsys在这些情况下截断输出。)


但我始终建议避免递归在较高的水平,编程可能。我们可以将这个功能作为管道:

  1. 配对使用zip
  2. 打开在结果列表中的每个元组为两个元素的列表输入列表中的元素:map (\(x, y) -> [x, y])
  3. 拼合结果列表使用concat

-of-列表,使代码看起来是这样的:

interleave xs ys = concat $ map (\(x, y) -> [x, y]) $ zip xs ys 

我发现这个代码比递归代码更容易理解,它需要你推理控制流 - 它只是一系列高级指令。

顺便说一句,你可以将它拖动到任意的concat的Elid中间mapzip

interleave xs ys = concatMap (\(x, y) -> [x, y]) $ zip xs ys 
interleave xs ys = concat $ zipWith (\(x, y) -> [x, y]) xs ys 
+0

非常感谢你的回放,你的代码非常好。但是,它不能满足最后的条件。当其中一个列表中没有其他元素时,它停止。你的代码给出如下输出:[1,2,3,4] [6,7,8] = [1,6,2,7,3 ,8,4],但它应该是[1,6,2,7,3,8] –

+0

我相信你可以弄清楚如何修改代码以适应练习。 –

2

interChange被称为有两个非空列表(x:xs)(y:ys),输出应该是一个列表开始x然后y然后更多的东西。所以你应该写点类似于

interChange (x:xs) (y:ys) = x : y : ... 
相关问题