2014-10-29 112 views
11

輸入:斯卡拉生成列表唯一對

val list = List(1, 2, 3, 4) 

所需的輸出:

Iterator((1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)) 

此代碼:

for (cur1 <- 0 until list.size; cur2 <- (cur1 + 1) until list.size) 
    yield (list(cur1), list(cur2)) 

,但它不是看起來最優的,有沒有更好的辦法做到這一點?

回答

21

There's a .combinations method built-in

scala> List(1,2,3,4).combinations(2).toList 
res0: List[List[Int]] = List(List(1, 2), List(1, 3), List(1, 4), List(2, 3), List(2, 4), List(3, 4)) 

它返回一個Iterator,但我加.toList只是用於打印結果的目的。如果你想在元組的形式你的結果,你可以這樣做:

scala> List(1,2,3,4).combinations(2).map{ case Seq(x, y) => (x, y) }.toList 
res1: List[(Int, Int)] = List((1,2), (1,3), (1,4), (2,3), (2,4), (3,4)) 

你提到的唯一性爲好,這樣你可以申請.distinct您輸入列表的獨特性是不是你的功能的前提條件,因爲.combination不會重複數據刪除爲你。

+0

正是我在尋找thx。通過唯一性我的意思是在結果 – 2014-10-29 10:45:52

+2

@ Co_42中沒有(1,2)和(2,1):替代解決方案:'list.tails.collect {case h :: tail => tail map {(h,_)} } .flatten.toList'。 – senia 2014-10-29 10:48:16

+0

@senia:你應該做出答案 – 2016-05-30 09:13:26

0

.combinations是使用foldLeft這種方式,用於產生任何大小,即不檢查在首位唯一另一種替代的解決方案的獨特任意組的適當方法:

val list = (1 to 10).toList 

val header :: tail = list 
tail.foldLeft((header, tail, List.empty[(Int, Int)])) { 
    case ((header, tail, res), elem) => 
    (elem, tail.drop(1), res ++ tail.map(x => (header, x))) 
}._3 

會產生:

res0: List[(Int, Int)] = List((1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (2,3), (2,4), (2,5), (2,6), (2,7), (2,8), (2,9), (2,10), (3,4), (3,5), (3,6), (3,7), (3,8), (3,9), (3,10), (4,5), (4,6), (4,7), (4,8), (4,9), (4,10), (5,6), (5,7), (5,8), (5,9), (5,10), (6,7), (6,8), (6,9), (6,10), (7,8), (7,9), (7,10), (8,9), (8,10), (9,10)) 

如果您希望有重複,那麼您可以將輸出列表轉換爲一個集合並將其重新放入一個列表中,但您將失去排序。因此,如果您想要具有唯一性,則不是推薦的方法,但如果要生成包含相等元素的所有對,則應該首選。

E.g.我在機器學習領域使用它來生成特徵空間中每對變量之間的所有產品,並且如果兩個或多個變量具有相同的值,我仍然希望產生與其產品相對應的新變量,即使這些新變量生成的「交互變量」將會有重複。