【问题标题】:Generalize list combinations to N lists将列表组合泛化为 N 个列表
【发布时间】:2013-11-15 02:53:07
【问题描述】:

在 Scala 中生成已知数量列表的组合非常简单。您可以使用理解:

for {
   elem1 <- list1
   elem2 <- list2 } yield List(elem1, elem2)

或者你可以使用脱糖版:

list1.flatMap( elem1 => list2.map(elem2 => List(elem1,elem2)))

以下套件,我想从 N 个列表中创建元素组合(N 在运行时已知)。按照组合器示例,3 个列表将是:

list1.flatMap( elem1 => list2.flatMap(elem2 => list3.map(elem3 => List(elem1,elem2,elem3)))

所以我看到了这个模式,我知道那里有一个递归,但我一直在努力确定它。

def combinations[T](lists:List[List[T]]): List[List[T]] = ???

有什么想法吗?

【问题讨论】:

  • 如果你允许自己scalaz,似乎你可以list1.replicateM[List](n) 其中n 是你想要的值的数量。

标签: list scala recursion combinatorics combinators


【解决方案1】:
def combinationList[T](ls:List[List[T]]):List[List[T]] = ls match {
     case Nil => Nil::Nil
     case head :: tail => val rec = combinationList[T](tail)
                          rec.flatMap(r => head.map(t => t::r))
}


scala> val l = List(List(1,2,3,4),List('a,'b,'c),List("x","y"))
l: List[List[Any]] = List(List(1, 2, 3, 4), List('a, 'b, 'c), List(x, y))

scala> combinationList(l)
res5: List[List[Any]] = List(List(1, 'a, x), List(2, 'a, x), List(3, 'a, x),
  List(4, 'a, x), List(1, 'b, x), List(2, 'b, x), List(3, 'b, x), List(4, 'b, x),
  List(1, 'c, x), List(2, 'c, x), List(3, 'c, x), List(4, 'c, x), List(1, 'a, y),
  List(2, 'a, y), List(3, 'a, y), List(4, 'a, y), List(1, 'b, y), List(2, 'b, y),
  List(3, 'b, y), List(4, 'b, y), List(1, 'c, y), List(2, 'c, y), List(3, 'c, y),
  List(4, 'c, y))

【讨论】:

    【解决方案2】:

    还有一种方法:

    def merge[T](a: List[List[T]],b:List[T]) = a match {
        case List() => for(i <- b) yield List(i) 
        case xs => for{ x <- xs; y<- b } yield y ::x 
    }
    
    scala> def com[T](ls: List[List[T]]) =  ls.foldLeft(List(List[T]()))((l,x) => merge(l,x))
    
    scala> val l = List(List(1,2,3,4),List('a,'b,'c),List("x","y"))
    l: List[List[Any]] = List(List(1, 2, 3, 4), List('a, 'b, 'c), List(x, y))
    
    scala> com(l)
    res1: List[List[Any]] = List(List(x, 'a, 1), List(y, 'a, 1), List(x, 'b, 1), Lis
    t(y, 'b, 1), List(x, 'c, 1), List(y, 'c, 1), List(x, 'a, 2), List(y, 'a, 2), Lis
    t(x, 'b, 2), List(y, 'b, 2), List(x, 'c, 2), List(y, 'c, 2), List(x, 'a, 3), Lis
    t(y, 'a, 3), List(x, 'b, 3), List(y, 'b, 3), List(x, 'c, 3), List(y, 'c, 3), Lis
    t(x, 'a, 4), List(y, 'a, 4), List(x, 'b, 4), List(y, 'b, 4), List(x, 'c, 4), Lis
    t(y, 'c, 4))
    

    【讨论】:

    • 为什么是-1。有什么解释吗?? >.
    【解决方案3】:

    另一种解决方案,与接受的答案非常相似,但恕我直言,这更具可读性:

    def helper[T](x: List[List[T]]): List[List[T]] = {
      x match {
        case Nil => List(Nil)
        case head :: tail => {
            for (
              n <- head;
              t <- helper(tail)
            ) yield n :: t
          }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-25
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      相关资源
      最近更新 更多