2011-12-12 35 views
10

我试图编写一个haskell函数,它接受两个整数列表并生成一个列表,其中包含两个列表中交替出现的元素。哈斯克尔 - 两个列表中的交替元素

我有功能:

blend xs ys 

一个例子:

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

应返回

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

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

这是从他们的元组中删除他们,我无法弄清楚如何实现。

回答

18

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

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

你甚至可以推广这种做法为任意数量的列表(我将离开这个给你),或采取列表的其余元素如果对方是空的:

blend _ ys = ys 
+0

非常酷的方式来做到这一点!谢谢。 – Shabu

6

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

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

...你可以用2个功能解决这个问题:

  1. 你需要一个元组(a, b)转换成一个列表[a, b]。尝试使用模式匹配!这个函数需要被应用(又名。映射)在你拥有的列表的所有元素上。
  2. 您将拥有一个列表,如[[1,4],[2,5],[3,6]],因此您需要一个将子列表连接成一个大列表的功能。

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

+1

我认为对于[原作]问题的答案在原始方向上继续是特别有用的(除非方向是完全错误的,在这种情况下,它不是)。 –

4

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

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]] 
2

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

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

我们可以也使这一点,免费

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


它是如何工作的:第一装饰两份名单与利弊运营商

\[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] 
+0

这有什么问题? – leftaroundabout