2012-08-02 88 views
4

說我有兩個列表:排序兩個列表一起在斯卡拉

List(("a",1),("b",4),("d",5),("a",7),("b",6)) 

List("a","b","c","d") 

,我想基於第一個列表,這樣我得到他們組:

List("a" -> List(("a",1),("a",7)), "b" -> List(("b",4),("b",6)), "d" -> List(("d",5))) 

實現此目標的最佳方法是什麼?我知道我可以使用groupBy和pattern匹配預先確定的值,但是當第二個列表未預先確定時,我會稍微卡住。

編輯:

我需要的對象在第二列表中的副本作爲處理名單的關鍵。我可能需要通過第二個列表中的on對象的參數進行分組,但仍然將整個對象保留爲鍵......如果這樣做合理的話。

List(("a",1),("b",4),("d",5),("a",7),("b",6)) 
List(("a",1,1),("b",2,3),("c",5,6),("d",6,7)) 

變爲:

List(("a",1,1) -> List(("a",1),("a",7)), ("b",2,3) -> List(("b",4),("b",6)), ("d",6,7) -> List(("d",5))) 

對不起,缺乏透明度的!

回答

5

按照您的編輯與for -comprehension:

for { 
    key <- second 
    pair <- first.groupBy(_._1).get(key) 
} yield key -> pair 

還是unsugared相當於:

second.flatMap(key => first.groupBy(_._1).get(key).map(key -> _)) 

這些都執行groupBy操作每個鍵。如果這是一個問題,你當然可以用稍微詳細避免:

val mappings = first.groupBy(_._1) 
second.flatMap(key => mappings.get(key).map(key -> _)) 

,並解決您的新的編輯:如果您需要在第二個列表以使每個項目使用它作爲一個重點首先,有幾種方法可以解決這個問題。例如,給定:

val first = List(("a", 1), ("b", 4), ("d", 5), ("a", 7), ("b", 6)) 
val second = List(("a", 1, 1), ("b", 2, 3), ("c", 5, 6), ("d", 6, 7)) 

或者:

for { 
    item @ (key, _, _) <- second 
    pair <- first.groupBy(_._1).get(key) 
} yield item -> pair 

或者:

根據需要
for { 
    item <- second 
    pair <- first.groupBy(_._1).get(item._1) 
} yield item -> pair 

作品。

+0

謝謝!最後的理解工作完美。 – Alex 2012-08-02 19:25:37

4

的解決方案是出奇的簡單:

first groupBy(_._1) toList 

結果:

List((a,List((a,1), (a,7))), (d,List((d,5))), (b,List((b,4), (b,6)))) 

哪裏first是你的第一個列表(什麼是第二個目的)?

+0

抱歉,由於缺乏清晰度,請參閱編輯。 – Alex 2012-08-02 11:53:54

1

另一種方式。

val first = List(("a",1),("b",4),("d",5),("a",7),("b",6)) 
val second = List(("a",1,1),("b",2,3),("c",5,6),("d",6,7)) 
first groupBy {k => second find {_._1 == k._1} get} 
+0

這不會維護訂單,這似乎是要求之一。 – 2012-08-02 12:33:52

+0

雖然你總是可以添加'toList.sortBy {_._ 1._1}',我會繼續自私地認爲他不需要維持排序,直到明確說明:) – Kaito 2012-08-02 12:57:45

-1
val a = List(("a",1),("b",4),("d",5),("a",7),("b",6)) 
val b = List(("a",1,1),("b",2,3),("c",5,6),("d",6,7)) 
val a1 = a.groupBy{ _._1 } 
b.flatMap{ x => a1.get(x._1).map{x -> _} } 

val a = List(("a",1),("b",4),("d",5),("a",7),("b",6)) 
val b = List(("a",1,1),("b",2,3),("c",5,6),("d",6,7)) 
b.view.map{ x => x -> a.filter{ _._1 == x._1 } }.filter{ _._2.nonEmpty }.toList 

第二種方法應是最有效的。