根据元组元素过滤列表

时间:2015-11-12 08:18:04

标签: scala

我有一个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))。

我该怎么做?

5 个答案:

答案 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))