我有以下列表
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))
任何替代方法也会受到赞赏。
答案 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))