Haskell - 来自两个列表的交替元素

时间:2011-12-12 06:20:04

标签: list haskell tuples alternating

我正在尝试编写一个haskell函数,该函数接收两个整数列表,并生成一个列表,其中包含从两个列表中交替获取的元素。

我有这个功能:

blend xs ys

一个例子:

blend [1,2,3] [4,5,6]

应该返回

[1,4,2,5,3,6]

我的逻辑是将两个列表压缩在一起,生成备用元素对,然后以某种方式将它们从元组中删除。

它将它们从元组中删除,我无法弄清楚如何实现。

5 个答案:

答案 0 :(得分:18)

如何在递归 - 下降期间交换参数?

blend (x:xs) ys = x:(blend ys xs)
blend _ _ = []

你甚至可以将这种方法概括为任意数量的列表(我会留给你)或者如果另一个列表为空,则采用列表的其余元素:

blend _ ys = ys

答案 1 :(得分:6)

我会假设这是作业。前提是您可以创建以下列表(如您所说):

[(1,4),(2,5),(3,6)]

...你可以用2个函数解决它:

  1. 您需要将元组(a, b)转换为列表[a, b]。尝试使用模式匹配!需要在列表的所有元素上应用(也就是映射)此函数。
  2. 您将拥有一个列表列表,例如[[1,4],[2,5],[3,6]],因此您需要一个将子列表连接成一个大列表的功能。
  3. 当然有其他方法可能更好地解决这个问题,但继续使用原始方法可能是个好主意。

答案 2 :(得分:5)

如果你想压缩,生成列表而不是元组:

concat $ zipWith (\x y -> [x,y]) [1,2,3] [4,5,6]

一些毫无意义的乐趣:

concat $ zipWith ((flip(:)).(:[])) [1,2,3] [4,5,6]  

可能是最简单的方法:

import Data.List
concat $ transpose [[1,2,3],[4,5,6]]

答案 3 :(得分:2)

不使用concat或显式递归的解决方案:

blend l = foldr($)[] . zipWith(.) (map(:)l) . map(:)

我们也可以使这个无点

blend' = (foldr($)[].) . (.map(:)) . zipWith(.) . map(:)

<小时/> 工作原理:首先用cons运算符

装饰两个列表
\[1,2,3] [4,5,6] -> [1:, 2:, 3:] [4:, 5:, 6:]

然后我们将它与功能组合

一起压缩
-> [(1:).(4:), (2:).(5:), (3:).(6:)]

最后将所有这些作品的应用从右侧折叠到空列表

-> (1:).(4:) $ (2:).(5:) $ (3:).(6:) $ [] = 1:4:2:5:3:6:[] = [1,4,2,5,3,6]

答案 4 :(得分:0)

您的 blend 函数似乎是 flatZip 的受限版本。 flatZip 函数与此类似,但适用于任意数量的不同长度的列表。使用 flatZip 来实现 blend 会导致 blend 也默认支持不同的长度。因此,在将输入列表修剪为相等长度是所需行为的一部分的情况下,使用基于 flatZip 的方法可能

名称 flatZip 指的是“一种 zip 式的 flattening 方式”。请注意 -ish 部分。我们可以通过组合 concattranspose 来实现该功能。我们可以在 blend 之上添加 flatZip 作为语法糖来验证我们的实现是否符合所需的行为。

import Data.List

flatZip = concat . transpose
flatZip([[1,2],[3],[4,5,6]]) --[1,3,4,2,5,6]

blend xs ys = flatZip [xs, ys]
blend [1,2,3] [4,5,6] --[1,4,2,5,3,6]