2013-04-18 50 views
2

說我有一個列表如下:如何讓scala集合包含獨特的元素? (「獨一無二」的定義)

val l = List((1, 2, "hi"), (1, 3, "hello"), (2, 3, "world"), (1, 2, "hello")) 

我想要的l明顯忽略元組的第三個元素的元素。也就是說,如果l的前兩個分量相同,則認爲它們是相同的。

所以makeDistinct(l)應該返回

List((1, 2, "hi"), (1, 3, "hello"), (2, 3, "world")) 

什麼是國家執行makeDistinct

編輯樣Scala和通用的最方式:我們可以自由地選擇哪個下降,訂貨無須保存。

+0

是否需要保留元素的排序? – sschaef

+0

@sschaef不需要保留順序。 – Jus12

+0

[Scala:刪除對象列表中的重複項]的可能重複(http://stackoverflow.com/questions/3912753/scala-remove-duplicates-in-list-of-objects) –

回答

3

如果你想用列表來做到這一點,使用groupBy

l.groupBy(x => (x._1, x._2)).map(kv => kv._2.head).toList 

如果你真的想要爲所有集合類型是通用的:

scala> import scala.collection.generic.CanBuildFrom 
import scala.collection.generic.CanBuildFrom 

scala> def distinct[A, B, C, CC[X] <: Traversable[X]](xs: CC[(A, B, C)])(implicit cbf: CanBuildFrom[Nothing, (A, B, C), CC[(A, B, C)]]): CC[(A, B, C)] = xs.groupBy(x => (x._1, x._2)).map(kv => kv._2.head).to[CC] 
warning: there were 1 feature warnings; re-run with -feature for details 
distinct: [A, B, C, CC[X] <: Traversable[X]](xs: CC[(A, B, C)])(implicit cbf: scala.collection.generic.CanBuildFrom[Nothing,(A, B, C),CC[(A, B, C)]])CC[(A, B, C)] 

scala> distinct(List((1, 2, "ok"), (1, 3, "ee"), (1, 2, "notok"))) 
res0: List[(Int, Int, String)] = List((1,3,ee), (1,2,ok)) 
+0

謝謝。這真的有幫助。 「相關問題」中的一般答案並未闡明我們如何將兩個要素匹配在一起。 – Jus12

1

您可以使用Ordering

scala> SortedSet(l: _*)(Ordering[(Int, Int)].on(x => (x._1, x._2))).toList 
res33: List[(Int, Int, String)] = List((1,2,hello), (1,3,hello), (2,3,world)) 

唯一的問題是保存了最後找到的元素。對於第一個,你需要扭轉名單:

scala> SortedSet(l.reverse: _*)(Ordering[(Int, Int)].on(x => (x._1, x._2))).toList 
res34: List[(Int, Int, String)] = List((1,2,hi), (1,3,hello), (2,3,world)) 

反之則不是最佳的,但也許它可以直接以相反的順序創建列表,這將避免不必要的中間表的構造。