我编写了一个合并两对列表的函数,在这种情况下,每个元素都包含一个字符和一个数字。
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)]
似乎在'else'情况下(b:bn:bs)不是开头加载的整个对列表,而是短版本(bs),因为它已经被'then'条件过滤了。 我正在寻找一种方法将原始(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)]
澄清:
也许合并不是一个充分的词。对于原始
ListA
中存在的ListZ
中的每个(第二个)元素,请在其后面写入元素。
另一个例子:
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]
答案 0 :(得分:1)
我有一系列的解决方案。首先,以下产生所需的输出。我认为这是指定的,但请注意mergeTupleList'
不再在它的第一行返回bList。虽然你的描述让我相信你确实想要那样,但这并没有达到预期的效果。
此解决方案的秘诀在于包含子函数tupleAB
,该函数会为第一个a:ab
执行所有tupling,在评估下一个bs
之前使用整个ab
列表}}对整个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
接下来,由于我们使用alist
中的每个字词来创建来自blist
的字词,
我在这里使用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
答案 1 :(得分: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