Scala:可变数量的阵列之间的笛卡尔积

时间:2016-01-13 11:37:39

标签: scala

我是Scala的新手,非常感谢任何方向或帮助解决以下问题。

输入

我有Map[String, Array[Double]],如下所示:

Map(foo -> Array(12, 25, 100), bar -> Array(0.1, 0.001))

Map可以包含1到10个键(取决于我的应用程序中的一些参数)。

处理

我想在所有键的数组之间应用笛卡尔积,并生成一个包含所有数组所有值的所有可能组合的结构。

在上面的示例中,笛卡尔积将创建3x2=6个不同的组合:(12, 0.1), (12, 0.001), (25, 0.1), (25, 0.01), (100,0.1) and (100, 0.01)

为了另一个例子,在某些情况下我可能有三个键:第一个键具有4个值的数组,第二个键具有5个值的数组,第三个键具有3个值的数组,在这种情况下该产品必须生成4x5x3=60种不同的组合。

所需的输出

类似的东西:

Map(config1 -> (foo -> 12, bar -> 0.1), config2 -> (foo -> 12, bar -> 0.001), config3 -> (foo -> 25, bar -> 0.1), config4 -> (foo -> 25, bar -> 0.001), config5 -> (foo -> 100, bar -> 0.1), config6 -> (foo -> 100, bar -> 0.001))

2 个答案:

答案 0 :(得分:1)

您可以使用for comprehension来创建两个列表的笛卡尔积,数组......

val start = Map(
  'foo -> Array(12, 25, 100), 
  'bar -> Array(0.1, 0.001), 
  'baz -> Array(2))

// transform arrays into lists with values paired with map key
val pairedWithKey = start.map { case (k,v) => v.map(i => k -> i).toList }

val accumulator = pairedWithKey.head.map(x => Vector(x))
val cartesianProd = pairedWithKey.tail.foldLeft(accumulator)( (acc, elem) => 
  for { x <- acc; y <- elem } yield x :+ y 
)

cartesianProd foreach println
// Vector(('foo,12), ('bar,0.1), ('baz,2))
// Vector(('foo,12), ('bar,0.001), ('baz,2))
// Vector(('foo,25), ('bar,0.1), ('baz,2))
// Vector(('foo,25), ('bar,0.001), ('baz,2))
// Vector(('foo,100), ('bar,0.1), ('baz,2))
// Vector(('foo,100), ('bar,0.001), ('baz,2))

在使用headtail之前,您可能需要添加一些检查。

答案 1 :(得分:1)

由于数组的数量是动态的,因此无法将结果作为结果

但是,您可以将递归用于您的目的:

def process(a: Map[String, Seq[Double]]) = {
    def product(a: List[(String, Seq[Double])]): Seq[List[(String, Double)]] =
        a match {
            case (name, values) :: tail =>
                for {
                    result <- product(tail)
                    value <- values
                } yield (name, value) :: result

            case Nil => Seq(List())
        }

    product(a.toList)
}


val a = Map("foo" -> List(12.0, 25.0, 100.0), "bar" -> List(0.1, 0.001))
println(process(a))

结果如下:

List(List((foo,12.0), (bar,0.1)), List((foo,25.0), (bar,0.1)), List((foo,100.0), (bar,0.1)), List((foo,12.0), (bar,0.001)), List((foo,25.0), (bar,0.001)), List((foo,100.0), (bar,0.001)))