Scala 两个列表的笛卡尔积

Scala 两个列表的笛卡尔积,scala,for-comprehension,Scala,For Comprehension,给定一个映射,其中一个数字与多个字符关联 scala> val conversion = Map("0" -> List("A", "B"), "1" -> List("C", "D")) conversion: scala.collection.immutable.Map[java.lang.String,List[java.lang.String]] = Map(0 -> List(A, B), 1 -> List(C, D)) 我想根据数字序列生成所有可

给定一个映射,其中一个数字与多个字符关联

scala> val conversion = Map("0" -> List("A", "B"), "1" -> List("C", "D"))
conversion: scala.collection.immutable.Map[java.lang.String,List[java.lang.String]] =
  Map(0 -> List(A, B), 1 -> List(C, D))
我想根据数字序列生成所有可能的字符序列。示例:

"00" -> List("AA", "AB", "BA", "BB")
"01" -> List("AC", "AD", "BC", "BD")
我可以用它来理解

scala> val number = "011"
number: java.lang.String = 011
为每个索引创建一个可能的字符序列

scala> val values = number map { case c => conversion(c.toString) }
values: scala.collection.immutable.IndexedSeq[List[java.lang.String]] =
  Vector(List(A, B), List(C, D), List(C, D))
生成所有可能的字符序列

scala> for {
     | a <- values(0)
     | b <- values(1)
     | c <- values(2)
     | } yield a+b+c
res13: List[java.lang.String] = List(ACC, ACD, ADC, ADD, BCC, BCD, BDC, BDD)
scala>for{

|a下面的建议不是用a来理解。但我认为这毕竟不是一个好主意,因为正如你所注意到的,你会被笛卡尔积的某个长度所束缚

scala> def cartesianProduct[T](xss: List[List[T]]): List[List[T]] = xss match {
     |   case Nil => List(Nil)
     |   case h :: t => for(xh <- h; xt <- cartesianProduct(t)) yield xh :: xt
     | }
cartesianProduct: [T](xss: List[List[T]])List[List[T]]

scala> val conversion = Map('0' -> List("A", "B"), '1' -> List("C", "D"))
conversion: scala.collection.immutable.Map[Char,List[java.lang.String]] = Map(0 -> List(A, B), 1 -> List(C, D))

scala> cartesianProduct("01".map(conversion).toList)
res9: List[List[java.lang.String]] = List(List(A, C), List(A, D), List(B, C), List(B, D))
scala>def cartesianProduct[T](xss:List[List[T]]):List[List[T]=xss匹配{
|案例无=>列表(无)
|案例h::t=>for(xh列表(“A”、“B”),“1”->List(“C”、“D”))
转换:scala.collection.immutable.Map[Char,List[java.lang.String]=Map(0->List(A,B),1->List(C,D))
scala>cartesianProduct(“01”.map(转换).toList)
res9:List[List[java.lang.String]]=List(List(A,C),List(A,D),List(B,C),List(B,D))
为什么不是尾部递归?
请注意,上面的递归函数是而不是尾部递归。这不是问题,因为
xss
将很短,除非在
xss
中有很多单例列表。这种情况是这样的,因为结果的大小随着
xss
的非单例元素的数量呈指数增长为此:

val conversion = Map('0' -> Seq("A", "B"), '1' -> Seq("C", "D"))

def permut(str: Seq[Char]): Seq[String] = str match {
  case Seq()  => Seq.empty
  case Seq(c) => conversion(c)
  case Seq(head, tail @ _*) =>
    val t = permut(tail)
    conversion(head).flatMap(pre => t.map(pre + _))
}

permut("011")

我只是这样做了如下,它的工作

    def cross(a:IndexedSeq[Tree], b:IndexedSeq[Tree]) = {
        a.map (p => b.map( o => (p,o))).flatten
    }

没有看到我处理的$Tree类型它也适用于任意集合。

谢谢Sciss,我接受了ziggystar的答案,因为他之前发布了它,而且两个答案都很好。我特别喜欢你的想法,将
分解为
平面图链中的
。@Mark Sciss的答案只在语法上与我的不同(至少对于构建组合的部件)。他使用
map
flatMap
,我使用理解语法糖,它被编译器翻译成Sciss的代码。唯一的区别是我提取了笛卡尔乘积的方法。@ziggystar太好了,现在我更了解幕后发生的事情。严格地说,你是什么ying to get不是笛卡尔乘积。如果您有
列表[T]
,则不能保证其大小,而且列表应该是同质的。