我有一个List [(Int,Int)]。
实施例
val a = List((1,2),(2,3),(1,4),(2,4),(5,6),(4,5),(1,8))
我想过滤此列表,以便如果多个元组具有相同的第一个元素(_1
中的相同值),则只保留第一个元组。
所以这里的预期答案是:
val ans=List((1,2),(2,3),(5,6),(4,5))
由于(1,2)
的第一个元素是1
,(1,4)
和(1,8)
同样适用,我们只保留第一个匹配项((1,2)
)和忽略其他人((1,4)
和(1,8)
)。
我该怎么做?
答案 0 :(得分:7)
a.groupBy(_._1).values.collect{case x::xs=>x}
根据@RégisJean-Gilles的建议编辑,
a.groupBy(_._1).values.map(_.head)
编辑,以保留订单
a.foldLeft(Map.empty[Int,(Int,Int)].empty){
case (r,(x,y))=> if(r.contains(x)) r else r+(x->(x,y))
}.values
答案 1 :(得分:4)
ListMap
让我们消除重复的密钥并保留顺序:
scala> val a= List((1,2),(2,3),(1,4),(2,4),(5,6),(4,5),(1,8))
a: List[(Int, Int)] = List((1,2), (2,3), (1,4), (2,4), (5,6), (4,5), (1,8))
scala> collection.immutable.ListMap(a.reverse: _*).toList.reverse
res0: List[(Int, Int)] = List((1,2), (2,3), (5,6), (4,5))
答案 2 :(得分:2)
scala> val a = List((1,2),(2,3),(1,4),(2,4),(5,6),(4,5),(1,8))
a: List[(Int, Int)] = List((1,2), (2,3), (1,4), (2,4), (5,6), (4,5), (1,8))
scala> a.reverse.toMap.toList
res7: List[(Int, Int)] = List((1,2), (4,5), (5,6), (2,3))
不保留订单,但非常简洁。
答案 3 :(得分:1)
这保留了顺序并保证只有在找到重复项时才保留第一个顺序,但它并不是一个非常有效的算法。长列表可能不是一个好主意。
scala> val a= List((1,2),(2,3),(1,4),(2,4),(5,6),(4,5),(1,8))
a: List[(Int, Int)] = List((1,2), (2,3), (1,4), (2,4), (5,6), (4,5), (1,8))
scala> a.filter(x => a.filter(_._1 == x._1).head == x)
res22: List[(Int, Int)] = List((1,2), (2,3), (5,6), (4,5))
答案 4 :(得分:1)
What you're asking for is almost .distinct
, with a different test for "duplicate". Let's see how the standard library does .distinct
:
/** Builds a new $coll from this $coll without any duplicate elements.
* $willNotTerminateInf
*
* @return A new $coll which contains the first occurrence of every element of this $coll.
*/
def distinct: Repr = {
val b = newBuilder
val seen = mutable.HashSet[A]()
for (x <- this) {
if (!seen(x)) {
b += x
seen += x
}
}
b.result()
}
We can do something a little less generic, but along the same lines:
import scala.collection.mutable.{ListBuffer, HashSet}
def distinctByFirst[A,B](xs:List[(A, B)]) = {
val b = new ListBuffer[(A,B)]
val seen = HashSet[A]()
for (x <- xs) {
if (!seen(x._1)) {
b += x
seen += x._1
}
}
b.result()
}
distinctByFirst(a)
//> res0: List[(Int, Int)] = List((1,2), (2,3), (5,6), (4,5))