2016-01-13 57 views
-4

我是斯卡拉的新手,希望能夠解決以下問題。斯卡拉:可變數量的數組之間的笛卡爾積

輸入

我有一個Map[String, Array[Double]],看起來像如下:

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

地圖可以包含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)) 
+0

你認爲有什麼解決辦法/試過這麼遠? – Dima

+0

TBH,無,任何解決方案將不勝感激 – Rami

回答

1

您可以使用爲理解創建兩個列表,數組的笛卡爾積...

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之前添加一些檢查。

+0

感謝您的整潔解決方案彼得 – Rami

+2

這不是問題:( – Dima

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)))