2017-02-10 130 views
0

我写了一个函数来合并两个对列表,在这种情况下,每个元素包含一个字符和一个数字。在匹配元素上合并列表

mergeTupleList [] blist = blist 
mergeTupleList alist [] = [] 
mergeTupleList (a:ab:as) (b:bn:bs) = 
    if ab == b 
     then a:[] ++ bn:[] ++ mergeTupleList (a:ab:as) (bs) 
     else [] ++ mergeTupleList (as) (b:bn:bs) 

listA = [('a',1),('b',1),('a',2),('b',1)] 
listZ = [('b',1),('z',1),('b',1),('z',2)] 

看来,在“其他”情况(b:BN:BS)是不是在一开始加载整个对列表,但短期的版本(BS),因为它已经被“然后过滤'条件。 我正在寻找一种方法将原始(b:bn:bs)列表传送给此功能。

输入和输出:

*Main> mergeTupleList ListA ListZ 
[('a',1),('z',1),('a',1),('z',2)] 

预期输出:

[('a',1),('z',1),('a',1),('z',2),('a',2),('z',1),('a',2),('z',2)] 

对于澄清:

也许合并是不足够的话。对原ListZ中存在的ListA中的每个(第二个)元素编写它后面的元素。

又如:

ListA = [1,0,3,0] 
ListZ = [0,8,0,9] 

*Main> mergeTupleList listA listZ 
[1,8,1,9] 

预期输出: [1,8,1,9,3,8,3,9]

+1

请您详细说明该功能应该做什么?给定的'listA'和'listZ'的预期输出与我期望合并两个列表不太一样。 – Michail

+0

也许合并不是合适的词。对于原ListZ中存在的ListA中的每个(秒)元素,都在其后面写入元素。 – Xui

+1

你应该编辑这个问题本身。 – Michail

回答

1

我有一系列为您的解决方案。首先,以下产生所需的输出。我认为这是指定的,但请注意mergeTupleList' 不再在第一行返回bList。虽然你的描述让我相信你确实需要这样做,但这并没有像预期的那样好。

的秘密就这个解决方案的子功能tupleAB,它完成所有的几倍第一a:ab,消耗评估未来ab对整个bs列表之前整个bs名单列入。

mergeTupleList' [] _ = [] 
mergeTupleList' alist [] = [] 
mergeTupleList' (a:ab:as) bbnbs = 
    let 
    tupleAB (b:bn:bs) = 
     if ab == b 
     then a:[] ++ bn:[] ++ tupleAB bs 
     else [] ++ tupleAB bs 
    tupleAB _ = [] 
    in tupleAB bbnbs ++ mergeTupleList' as bbnbs 

接下来是所有那些调皮:[] ++

mergeTupleList'' [] _ = [] 
mergeTupleList'' alist [] = [] 
mergeTupleList'' (a:ab:as) bbnbs = 
    let 
    tupleAB (b:bn:bs) = 
     if ab == b 
     then a : bn : tupleAB bs 
     else tupleAB bs 
    tupleAB _ = [] 
    in tupleAB bbnbs ++ mergeTupleList'' as bbnbs 

将上述溶液有一定的悬空情况下表达式的轻微清理。在其中一个名单没有编号的情况下,我们做什么?如果我们将每个前两项变为一对,我们有成对(成对)的列表。这个转换功能改变你的列表。

pairListCvt :: [a] -> [(a,a)] 
pairListCvt (a:b:cs) = (a,b) : pairListCvt cs 
pairListCvt (a:[]) = [] --maybe should be error? 
pairListCvt _ = [] 

listACvt = pairListCvt listA 
listZCvt = pairListCvt listZ 

现在,再次重写,我们有更少的不匹配的模式,因此可能出现更少的错误。这是选择一种类型以提供一点安全性的示例;类型安全。

mergeTupleList''' [] _ = [] 
mergeTupleList''' alist [] = [] 
mergeTupleList''' ((a,ab):as) bbnbs = 
    let 
    tupleAB ((b,bn):bs) = 
     if ab == b 
     then (a , bn) : tupleAB bs 
     else mergeTupleList''' as ((b,bn):bs) 
    tupleAB _ = [] 
    in tupleAB bbnbs ++ mergeTupleList''' as bbnbs 

其次,由于我们使用的每个术语alistblist创造条件, 我在这里使用一个map

mergeTupleList'''' as bbns = 
    let 
    tupleAB ((b,bn):bs) (a,ab) = 
     if ab == b 
     then (a, bn) : tupleAB bs (a,ab) 
     else tupleAB bs (a,ab) 
    tupleAB [] _ = [] 
    in concat $ map (tupleAB bbns) as 

最后,内tupleAB可以配制为fold;通过对列表进行逐个元素的分解来递增地构建数据结构。该折叠的核心逻辑现在保存在f

mergeTupleList''''' as bbns = 
    let 
    tupleAB bs aab = foldr (f aab) [] bs 
    f (a,ab) (b,bn) acc 
     | ab == b  = (a,bn) : acc 
     | otherwise  = acc 
    in concat $ map (tupleAB bbns) as 

我更喜欢哪里绑定,让绑定,风格。 Alghouth存在记忆表现问题,我不明白这个选择。

mergeTupleListW as bbns = concat $ map (tupleAB bbns) as 
    where 
    tupleAB bs aab = foldr (f aab) [] bs 
    f (a,ab) (b,bn) acc 
     | ab == b  = (a,bn) : acc 
     | otherwise  = acc 

额外信用。他是写成List monad的函数。

mergeTupleListM as bbns = 
    do a <- as 
    tupleAB bbns a 
    where 
    tupleAB bs aab = foldr (f aab) [] bs 
    f (a,ab) (b,bn) acc 
     | ab == b  = (a,bn) : acc 
     | otherwise  = acc 
+0

谢谢,你又救了我!其实我不知道我在用':[] ++'做什么 – Xui

0

这个问题已经回答了,但这里是我想通过评论的帮助。 首先我们创建一个groupByTwo函数来打破包含每两个元素的列表中的listA

groupByTwo [] = [] 
groupByTwo list = 
(take 2 list) : (groupByTwo (drop 2 list)) 

然后我们创建一个mergeTupleList'功能列表清单中的每一个元素上运行简单mergeTupleList

mergeTupleList' [] _ = [] 
mergeTupleList' (a:as) list2 = 
    mergeTupleList a list2 ++ mergeTupleList' as list2 

最后,第三个函数叫做groupTupleMerge,以使生活更轻松。

groupTupleMerge list1 list2 = 
    mergeTupleList' (groupByTwo list1) list2