如何使用scala基于某些元素从元组列表中查找唯一元素?

时间:2015-11-27 11:39:52

标签: scala

我有以下列表

val a = List(("name1","add1","city1",10),("name1","add1","city1",10),

("name2","add2","city2",10),("name2","add2","city2",20),("name3","add3","city3",20))

我想根据元组的前三个值从上面的列表中获取不同的元素。从列表中找到不同的元素时,不应考虑第四个值。

我想要关注输出:

val output = List(("name1","add1","city1",10),("name2","add2","city2",10),

("name3","add3","city3",20))

是否有可能获得以上输出?

据我所知,如果重复整个元组/值,distinct会起作用。我尝试了distinct,如下面的

val b = List(("name1","add1","city1",10),("name1","add1","city1",10),("name2","add2","city2",10),
("name2","add2","city2",20),("name3","add3","city3",20)).distinct

但它输出为 -

List(("name1","add1","city1",10),("name2","add2","city2",10),
("name2","add2","city2",20),("name3","add3","city3",20))

任何替代方法也会受到赞赏。

5 个答案:

答案 0 :(得分:4)

像这样使用groupBy

a.groupBy( v => (v._1,v._2,v._3)).keys.toList

这构造了一个Map,其中每个键根据定义是上面lambda函数中所需的唯一三元组。

它是否还包括元组中的最后一个元素,为每个键获取第一个元素,如下所示

a.groupBy( v => (v._1,v._2,v._3)).mapValues(_.head)

答案 1 :(得分:3)

如果输出列表的顺序不重要(即您很高兴获得List(("name3","add3","city3",20),("name1","add1","city1",10),("name2","add2","city2",10))),则以下工作方式如下:

a.groupBy(v => (v._1,v._2,v._3)).values.map(_.head).toList

(由于Scala集合设计,您将看到最多包含4个元素的输出列表的订单,但将使用超过该尺寸HashMap。)如果您确实需要保留订单,你可以做一些事情(概括一点)

def distinctBy[A, B](xs: Seq[A], f: A => B) = {
  val seen = LinkedHashMap.empty[B, A]
  xs.foreach { x =>
    val key = f(x)
    if (!seen.contains(key)) { seen.update(key, x) }
  }
  seen.values.toList
}

distinctBy(a, v => (v._1, v._2, v._3))

答案 2 :(得分:2)

你可以尝试

a.map{case x@(name, add, city, _) => (name,add,city) -> x}.toMap.values.toList

答案 3 :(得分:1)

确保保留列表中的第一个

  type String3 = (String, String, String)
  type String3Int = (String, String, String, Int)
  a.foldLeft(collection.immutable.ListMap.empty[String3, String3Int]) {
    case (a, b) => if (a.contains((b._1, b._2, b._3))) {
      a
    } else a + ((b._1, b._2, b._3) -> b)
  }.values.toList

答案 4 :(得分:0)

一个简单的解决方案是将List转换为Set。集合不包含重复项:check the documentation

 val setOfTuples = a.toSet
 println(setOfTuples)

输出:Set((1,1), (1,2), (1,3), (2,1))