Haskell:合并列表列表

时间:2018-12-13 07:27:20

标签: haskell

给出了列表对::[a,a]的列表,我想返回列表的可能组合,其中子列表已合并到下一个匹配的头的最后一个匹配头上。

例如     -如果前后匹配则合并两个列表

merge :: Eq a => [[a]] -> [[a]]
merge (x:y:ys) | last x == head y = merge $ (x ++ (drop 1 y)) : ys
               | otherwise    = []
merge xs       = xs

combinations :: Eq a => [[a]] -> [[a]]
combinations = nub . concatMap merge . permutations

λ= merge [1,2] [2,3]
[1,2,3]


-- there should be no duplicate results
λ= combinations [[1,3],[1,3],[1,3],[1,3],[2,1],[2,1],[2,1],[2,2],[3,2],[3,2],[3,2]]
[[1,3,2,2,1,3,2,1,3,2,1,3],[1,3,2,1,3,2,2,1,3,2,1,3],1,3,2,1,3,2,1,3,2,2,1,3]]

-- the result must be a completely merged list or an empty list
λ= combinations [[1,3], [3,1], [2,2]]
[]

λ= combinations [[1,3], [3, 1]]
[[1,3,1],[3,1,3]]

λ= combinations [[1,3],[3,1],[3,1]]
[[3,1,3,1]]

我无法完全绕开有效执行此操作所需的递归。

2 个答案:

答案 0 :(得分:1)

我以这个解决方案结束了,但是它包含重复项(您可以使用lena.jpg删除它们)。

Data.List(nub)

答案 1 :(得分:0)

我不确定我是否完全了解您想做什么,因此这里仅是一些注意事项和提示。

  

给出了列表对::[a,a]

的列表      

(...)例如

     

λ= merge [1,2] [2,3]

首先,这些不是成对的列表,列表中的每个元素都是整数而不是成对的。它们只是带有两个元素的列表。因此,您可以说它们的类型为[Int]或实例类型为[a]

  

子列表已合并到下一个子匹配标题的最后一个。

这表明列表的大小将增加,并且您将不断需要检查它们的第一个和最后一个元素。检查列表的最后一个元素意味着每次都要遍历它。您要避免这种情况。

这建议使用带有易于访问的附加信息的列表表示。您只需要最后一个元素,但出于对称性考虑,我将放在最后。

-- lists together with their last element
data CL a = CL [a] a a 

cl :: [a] -> CL a 
cl [] = error "CL from empty list"
cl xs = CL xs (head xs) (last xs)

clSafe :: [a] -> Maybe (CL a)
clSafe [] = Nothing
clSafe xs = Just (cl xs)

clFirst (CL _ x _) = x
clLast  (CL _ _ x) = x

compatible cs ds = clLast cs == clFirst ds

也许更好,也许您应该拥有

data CL a = CL [a] a a | Nil 

并包括一个与所有其他列表兼容的空列表。

要考虑的另一点是,例如,如果您有一个列表xs并想找到列表ys合并为ys++xs,那么您希望它非常简单使用给定的最后一个元素访问所有ys。这表明您应该将它们存储在适当的结构中。也许是哈希表。