我有
val a = List((1,2), (1,3), (3,4), (3,5), (4,5))
我正在使用A.groupBy(_._1)
,即groupBy和第一个元素。但是,它给我输出
Map(1 -> List((1,2) , (1,3)) , 3 -> List((3,4), (3,5)), 4 -> List((4,5)))
但是,我想要回答
Map(1 -> List(2, 3), 3 -> List(4,5) , 4 -> List(5))
那么,我该怎么做呢?
答案 0 :(得分:9)
您可以通过跟踪mapValues
(以及每个值map
来提取第二个元素)来实现这一点:
scala> a.groupBy(_._1).mapValues(_.map(_._2))
res2: scala.collection.immutable.Map[Int,List[Int]] = Map(4 -> List(5), 1 -> List(2, 3), 3 -> List(4, 5))
答案 1 :(得分:5)
通过模式匹配和Map#withDefaultValue
:
scala> a.foldLeft(Map.empty[Int, List[Int]].withDefaultValue(Nil)){
case(r, (x, y)) => r.updated(x, r(x):+y)
}
res0: scala.collection.immutable.Map[Int,List[Int]] =
Map(1 -> List(2, 3), 3 -> List(4, 5), 4 -> List(5))
有两点:
Map#withDefaultValue
将获得具有给定默认值的地图,然后您无需检查地图是否包含密钥。
当scala中的某个地方需要函数值(x1,x2,..,xn) => y
时,您总是可以在此处使用匹配case(x1,x2,..,xn) => y
的模式,编译器会将其转换为函数auto。请查看8.5 Pattern Matching Anonymous Functions以获取更多信息。
抱歉我的英语很差。
答案 2 :(得分:2)
作为变体:
<li ng-repeat="post in posts | filter:myFilter">
答案 3 :(得分:1)
您也可以使用foldLeft
进行一次迭代。
a.foldLeft(Map.empty[Int, List[Int]])((map, t) =>
if(map.contains(t._1)) map + (t._1 -> (t._2 :: map(t._1)))
else map + (t._1 -> List(t._2)))
scala.collection.immutable.Map[Int,List[Int]] = Map(1 -> List(3, 2), 3 ->
List(5, 4), 4 -> List(5))
如果列表中元素的顺序很重要,则需要包含reverse
。
a.foldLeft(Map.empty[Int, List[Int]])((map, t) =>
if(map.contains(t._1)) (map + (t._1 -> (t._2 :: map(t._1)).reverse))
else map + (t._1 -> List(t._2)))
scala.collection.immutable.Map[Int,List[Int]] = Map(1 -> List(2, 3), 3 ->
List(4, 5), 4 -> List(5))
答案 4 :(得分:1)
从Scala 2.13
起,可以使用groupMap
这样您就可以只写:
// val list = List((1, 2), (1, 3), (3, 4), (3, 5), (4, 5))
list.groupMap(_._1)(_._2)
// Map(1 -> List(2, 3), 3 -> List(4, 5), 4 -> List(5))