2

假设我有一个如下列表:

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

什么是最类似于 Scala 和通用的实现方式makeDistinct

编辑:我们可以自由选择要删除的内容,并且不需要保留订单。

4

2 回答 2

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))
于 2013-04-18T12:46:04.357 回答
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))

反向不是最优的,但也许可以直接以相反的顺序创建列表,这将避免构建不必要的中间列表。

于 2013-04-18T15:20:30.490 回答