简体   繁体   English

用于列表列表中元组序列的Haskell算法

[英]Haskell algorithm for sequence of tuples in a list of lists

I was playing around a bit in Haskell to get familiar with it, but got stuck at the following problem: 我在Haskell玩了些游戏以熟悉它,但是遇到了以下问题:

I want to define a function that, given a list containing some amount of other lists, each containing 0 or more tuples, creates a new list as following: 我想定义一个函数,给定一个包含一些其他列表(每个列表包含0个或多个元组)的列表,创建一个新列表,如下所示:

*Main> foo 
    [
      [ (1,2), (3,4)  ],
      [ (5,6)         ],
      [ (7,8), (9,10) ]
    ]


  = [
      [ (1,2), (5,6), (7,8)  ],
      [ (1,2), (5,6), (9,10) ],
      [ (3,4), (5,6), (7,8)  ],
      [ (3,4), (5,6), (9,10) ]
    ]

So, in other words, the function should compose a list with every tuple from the first list combined with in each case one of the other tuples in the N remaining lists. 因此,换句话说,该函数应组成一个列表,其中第一个列表中的每个元组应与N个其余列表中的其他每个元组分别组合。

I was trying to write a recursive algorithm for this, but can't wrap my head around dealing with the N amount of other lists to combine tuples with. 我试图为此编写一个递归算法,但是无法处理与N个其他列表结合在一起的元组。 For just two lists of tuples, I would write something like: 对于仅两个元组列表,我将编写如下内容:

composeList [] _        = []
composeList (x:xs) list = composeTuples x list ++ composeList xs list

composeTuples _ []     = []
composeTuples t (x:xs) = [t,x] : composeTuples t xs

This gives me: 这给了我:

*Main Data.List> composeList [(1,2),(3,4)] [(5,6),(7,8)]

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

Though I can't seem to put the pieces together and make it work for any number of lists, each with any (>=0) number of tuples. 尽管我似乎无法将各个部分组合在一起,以使其适用于任意数量的列表,每个列表都具有任意(> = 0)个元组。

I'm both interested in solving this issue with some of Haskell's predefined functions (if possible), as well as with a somewhat similar approach as the one I was going for in the example above. 我都想通过使用Haskell的一些预定义函数(如果可能)以及一种与上例中使用的方法类似的方法来解决此问题。

Thanks in advance! 提前致谢!

This is simply the list monad, selecting an element from each list non-deterministically. 这只是列表单子,是不确定地从每个列表中选择一个元素。

The function you're looking for is sequence :: Monad m => [ma] -> m [a] from Control.Monad 您要查找的函数是Control.Monad sequence :: Monad m => [ma] -> m [a]

λ. let as = [(1,2),(3,4)]
λ. let bs = [(5,6)]
λ. let cs = [(7,8),(9,10)]
λ. let xss = [as, bs, cs]
λ. sequence xss
  [[(1,2),(5,6),(7,8)]
  ,[(1,2),(5,6),(9,10)]
  ,[(3,4),(5,6),(7,8)]
  ,[(3,4),(5,6),(9,10)]
  ]

Here's a recursive solution 这是一个递归解决方案

solution :: [[a]] -> [[a]]
solution (x: xs) = [y: ys | y <- x, ys <- solution xs]
solution []      = [[]]

The idea behind the solution is the following: prepend each element of the head of list to every list you get from recursively computing the result for the tail of the input list. 解决方案的思想如下:将列表头的每个元素放在每个通过递归计算输入列表尾部结果而获得的列表中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM