2011-05-23 15 views
0

所有可能的排列考慮這樣的地圖:值的這樣的地圖

Map("one" -> Iterable(1,2,3,4), "two" -> Iterable(3,4,5), "three" -> Iterable(1,2)) 

我想Iterable下元素的所有可能的排列的列表,每個關鍵的一個要素。對於這個例子,這將是這樣的:

// first element of "one", first element of "two", first element of "three" 
// second element of "one", second element of "two", second element of "three" 
// third element of "one", third element of "two", first element of "three" 
// etc. 
Seq(Iterable(1,3,1), Iterable(2,4,2), Iterable(3,5,1),...) 

什麼將是一個很好的方法來實現這一目標?

+1

這不是排列組合。在所有可能的順序中,排列是單個集合,所以像1,2,3; 1,3,2; 2,1,3; 2,3,1; 3,1,2; 3,2,1。你可能意指的是「換位」(第二個索引第一個索引和第一個索引)。 – 2011-05-23 13:14:09

+0

什麼定義了鍵的順序,因爲Map鍵否則沒有排序? – 2011-05-23 13:36:39

+0

@保羅我不希望它被訂購。考慮'Iterable(1,2,3)','Iterable(2,3,1)','Iterable(3,1,2)'和'Iterable(3,2,1)'是相同的。 – folone 2011-05-23 13:58:48

回答

3
val m = Map("one" -> Iterable(1,2,3,4), "two" -> Iterable(5,6,7), "three" -> Iterable(8,9)) 

如果你想每一個組合:

for (a <- m("one"); b <- m("two"); c <- m("three")) yield Iterable(a,b,c) 

如果希望每個迭代一起前進,但停止時最短的exhuasted:

(m("one"), m("two"), m("three")).zipped.map((a,b,c) => Iterable(a,b,c)) 

如果希望每個迭代當最長的那個已經用完時,環繞但停止:

val maxlen = m.values.map(_.size).max 
def icf[A](i: Iterable[A]) = Iterator.continually(i).flatMap(identity).take(maxlen).toList 
(icf(m("one")), icf(m("two")), icf(m("three"))).zipped.map((a,b,c) => Iterable(a,b,c)) 

編輯:如果你想要任意數量的輸入列表,那麼你最好使用遞歸函數。對於笛卡爾積:

def cart[A](iia: Iterable[Iterable[A]]): List[List[A]] = { 
    if (iia.isEmpty) List() 
    else { 
    val h = iia.head 
    val t = iia.tail 
    if (t.isEmpty) h.map(a => List(a)).toList 
    else h.toList.map(a => cart(t).map(x => a :: x)).flatten 
    } 
} 

和更換zipped你想要的東西,如:

def zipper[A](iia: Iterable[Iterable[A]]): List[List[A]] = { 
    def zipp(iia: Iterable[Iterator[A]], part: List[List[A]] = Nil): List[List[A]] = { 
    if (iia.isEmpty || !iia.forall(_.hasNext)) part 
    else zipp(iia, iia.map(_.next).toList :: part) 
    } 
    zipp(iia.map(_.iterator)) 
} 

您可以嘗試這些了與cart(m.values)zipper(m.values),並zipper(m.values.map(icf))

+0

所有這些都有硬鍵連接使用的密鑰數量。有沒有一種整潔的方式來處理任何數量的條目的地圖? – 2011-05-23 18:59:31

+0

@Paul - 給出的例子。 – 2011-05-23 20:33:11

+0

太好了,謝謝。我會去了解笛卡爾產品。 – folone 2011-05-24 06:28:36

2

如果你是一個笛卡爾產品,我有一個solution for lists of lists of something

xproduct (List (List (1, 2, 3, 4), List (3, 4, 5), List (1, 2)))  
res3: List[List[_]] = List(List(1, 3, 1), List(2, 3, 1), List(3, 3, 1), List(4, 3, 1), List(1, 3, 2), List(2, 3, 2), List(3, 3, 2), List(4, 3, 2), List(1, 4, 1), List(2, 4, 1), List(3, 4, 1), List(4, 4, 1), List(1, 4, 2), List(2, 4, 2), List(3, 4, 2), List(4, 4, 2), List(1, 5, 1), List(2, 5, 1), List(3, 5, 1), List(4, 5, 1), List(1, 5, 2), List(2, 5, 2), List(3, 5, 2), List(4, 5, 2)) 

與雷克斯」 M調用它:

xproduct (List (m("one").toList, m("two").toList, m("three").toList)) 
1

看一看this answer。問題是關於要組合的固定數目的列表,但一些答案解決了一般情況。

相關問題