我刚刚开始使用Haskell而且我不知道该如何做到这一点但是当我有一个像[1,2,3,4] [5,6,7,8,9,10,11,12]这样的输入时输出应为[[(1,5),(2,6),(3,7),(4,8)] [(1,9),(2,10),(3,11),( 4,12)]] . 我试着做点什么,看下面的代码 . 但这仅适用于特定大小的列表 . 我确信必须有一种方法可以更有效地执行此操作,并且递归地提供任何大小的列表,有人可以帮我这个吗?
splitlist :: [a] -> [b] -> [[(a,b)]]
splitlist list1 list2 = [a,b,c] where
n = length list1
a = zip list1 list2
nlist = drop n list2
b = zip list1 nlist
nnlist = drop n nlist
c = zip list1 nnlist
4 回答
当第一个列表是两个中最长的列表时,first answer不起作用;对于这么简单的任务来说,second answer似乎过长了 .
修改第一个答案的代码很容易,
适用于这两种情况,也有无限列表 .
你有正确的方法,但你只需要递归,而不是枚举你经历的周期数:
所以,例如,
一个有趣的问题!
cycle
可能在这种情况下有所帮助,它重复列表无限时间的元素,如所以,何时用
[5,6,7,8,9,10,11,12]
压缩将是所需的结果[(1,5),(2,6),(3,7),(4,8),(1,9),(2,10),(3,11),(4,12)]
然后使用chunksOf(在Data.List.Split中定义)将其分组为[[(a, b)]]
类型为:P.S this solution only work for finite lists
另一个答案显示了如何重用库函数 . 但是,它有一个小缺陷:它在开始返回结果之前将其参数强制进入内存,因此它与Haskell的其余惰性基础结构不能完全一致 . 在这个答案中,我将展示如何编写一个版本:
开始立即产生输出(一旦明确两个列表都是非空的)
使用无限输入
在任何给定时间强制最多两倍长度的元素值的元素进入内存
我们将构建在另一个答案中使用的所有部分,但是它们的lazified版本:不是使用
Int
作为长度,我们将隐式使用[a]
类型的列表作为其自身长度的惰性表示 . 我们需要的第一件事是两个懒数的比较 . 稍后会发现我们的比较返回不仅仅是哪个数字更大,而是两个数字的差异 .接下来我们需要
chunksOf
;我们将根据splitAt
的lazified版本实现它 . 后者应该使用"lazy"长度将其列表参数拆分为 . 我们小心翼翼地尽可能快地开始生成元素 - 也就是说,只要我们知道要分割的索引大于0并且我们分割的列表是非空的 .我们的惰性
chunksOf
变体现在可以使用lazySplitAt
作为子例程 . 我们再次将"lazy"数作为我们的第一个参数;并且我们尽可能早地生成输出列表的结构,将(:)
调用为最外层的函数调用 .有了这些部分,我们可以使用基本相同的实现,交换
length
/(<=)
/chunksOf
的惰性变体 .我们可以在ghci中尝试一下:
无限列表可以很好地用作任何一个参数:
......或作为两个论点: