我有以下清单
val a = List(("name1","add1","city1",10),("name1","add1","city1",10),
("name2","add2","city2",10),("name2","add2","city2",20),("name3","add3","city3",20))
Run Code Online (Sandbox Code Playgroud)
我想要基于元组的前三个值从上面的列表中区分出不同的元素。从列表中查找不同元素时,不应考虑第四个值。
我想要以下输出:
val output = List(("name1","add1","city1",10),("name2","add2","city2",10),
("name3","add3","city3",20))
Run Code Online (Sandbox Code Playgroud)
是否有可能超过输出?
据我所知,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
Run Code Online (Sandbox Code Playgroud)
但它给出的输出为-
List(("name1","add1","city1",10),("name2","add2","city2",10),
("name2","add2","city2",20),("name3","add3","city3",20))
Run Code Online (Sandbox Code Playgroud)
任何替代方法也将不胜感激。
使用groupBy这样的
a.groupBy( v => (v._1,v._2,v._3)).keys.toList
Run Code Online (Sandbox Code Playgroud)
这就构造了一个Map,其中每个键根据上面的lambda函数的要求定义为唯一的三元组。
如果它还包含元组中的最后一个元素,则为每个键获取第一个元素,如下所示
a.groupBy( v => (v._1,v._2,v._3)).mapValues(_.head)
Run Code Online (Sandbox Code Playgroud)
如果输出列表的顺序不重要(即您很高兴获得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
Run Code Online (Sandbox Code Playgroud)
(由于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))
Run Code Online (Sandbox Code Playgroud)