如何使用Scala根据某些元素从元组列表中查找唯一元素?

5

我有以下列表

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仅在整个元组/值被复制时才起作用。我尝试使用以下代码进行去重:

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

任何其他方案也将不胜感激。

1
可能是 根据元组元素过滤列表 的重复问题。 - The Archetypal Paul
5个回答

5

使用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)

5
如果输出列表的顺序不重要(例如,您愿意获得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))

3

您可以尝试

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

2
为了确保列表中的第一个保留,
  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

1
这会保留早期元素,以防冲突。这正是我想要的。感谢代码片段。 - moonkey

0
一个简单的解决方案是将List转换为Set。Set不包含重复项:查看文档
 val setOfTuples = a.toSet
 println(setOfTuples)

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接