我正在尝试解决对scala元组进行分组和求和并保持键顺序的问题。
说
val arrayTuples = Array((A, 38) , (B, 150), (B, 250), (B, 890), (D, 600), (C, 515))
到
Map(A -> 38, B -> 1290, D -> 600, C -> 515)
正在做
val aMap = arrayTuples .groupBy(_._1)
似乎弄乱了顺序。帮助表示赞赏。
编辑:保持首次遇到的顺序。
答案 0 :(得分:5)
您可以使用#h1-container h1 {
/*Your rules*/
}
来保留顺序,但是如果您希望按照注释中的说明从左至右进行排序,则需要一些额外的步骤。
ListMap
由于//note the new order of elements
val arrayTuples =
Array(('A', 38), ('B', 150), ('D', 600), ('B', 250), ('C', 515), ('B', 890))
import collection.immutable.ListMap
arrayTuples.foldRight(ListMap[Char,Int]()) {
case ((c,n), lm) => lm.updated(c , lm.getOrElse(c, 0)+n)
}.foldRight(ListMap[Char,Int]()){case (elem,lm) => lm+elem}
//res0: ListMap[Char,Int] = ListMap(A -> 38, B -> 1290, D -> 600, C -> 515)
保留了最后一个顺序,在这种情况下会将ListMap
项移到末尾,所以我决定移至B
,这将{{1} }输入到末尾,然后再次foldRight
来颠倒整个过程。
答案 1 :(得分:3)
您可以像这样获得插入顺序图:
import scala.collection.immutable.ListMap
val tuples = List(("A", 38) , ("B", 150), ("B", 250), ("B", 890), ("C", 515), ("D", 600))
val initMap = ListMap.empty[String, List[(String, Int)]].withDefaultValue(List.empty)
val aMap = tuples.foldLeft(initMap) { case (acc, (k, v)) =>
val newList = (k -> v) :: acc(k)
acc + (k -> newList)
}
println(aMap) // Map(A -> List((A,38)), B -> List((B,890), (B,250), (B,150)), C -> List((C,515)), D -> List((D,600)))
答案 2 :(得分:2)
默认情况下,scala Map是未排序的集合,但是您可以使用ListMap:
val summedTuples = arrayTuples
.groupBy(_._1)
.mapValues(_.map(_._2).sum)
.toSeq.sortBy(_._1)
// ArrayBuffer((A,38), (B,1290), (C,515), (D,600))
ListMap(summedTuples: _*)
// Map(A -> 38, B -> 1290, C -> 515, D -> 600)
编辑:因此,在重新阅读问题以及有关“首次遇到的”排序的说明后,我不再只是删除我的答案,而是在下面稍加修改。我仍然更喜欢上面接受的答案,但是选择其他方法也不会受伤:
import scala.collection.immutable.ListMap
val arrayTuples = Array(("A", 38) , ("B", 150), ("B", 250), ("B", 890), ("D", 600), ("C", 515))
val summedTuples = arrayTuples
.groupBy(_._1)
.mapValues(_.map(_._2).sum)
.toSeq.sortBy(k => arrayTuples.indexWhere(_._1 == k._1)) // yes, I'm sorting by the original order...
ListMap(summedTuples : _*) // Map(A -> 38, B -> 1290, D -> 600, C -> 515)