14

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

我有这个功能:

blend xs ys

一个例子:

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

应该返回

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

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

它将它们从我不知道如何实现的元组中删除。

4

5 回答 5

21

在递归下降期间交换参数怎么样?

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

您甚至可以将这种方法推广到任意数量的列表(我将把它留给您),或者如果另一个为空,则获取列表的其余元素:

blend _ ys = ys
于 2011-12-12T06:26:36.313 回答
8

如果要压缩,请生成列表而不是元组:

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]]
于 2011-12-12T08:03:06.663 回答
7

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

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

...您可以使用 2 个功能来解决它​​:

  1. 您需要将 tuple(a, b)转换为 list [a, b]。尝试使用模式匹配!此功能需要应用于(也称为映射)您拥有的列表的所有元素。
  2. 您将拥有一个列表列表,例如[[1,4],[2,5],[3,6]],因此您需要一个将子列表连接成一个大列表的函数。

当然,还有其他可能更好的方法来解决这个问题,但继续你原来的方法可能是个好主意。

于 2011-12-12T06:31:58.623 回答
3

不使用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]
于 2011-12-12T11:56:19.947 回答
0

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

这个名字flatZip指的是“一种zipish 的方式flatten”。请注意-ish部分。我们可以通过组合来实现这个concat功能transpose。我们可以添加语法糖来验证我们的实现是否匹配所需的行为blendflatZip

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]
于 2020-12-22T12:23:14.667 回答