Суммарное значение ключевой суммы Scala за Seq (ключ, значение) при сохранении порядка - PullRequest
5 голосов
/ 25 апреля 2019

Я пытаюсь решить проблему с группировкой и суммированием по кортежам 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)

Doing:

val aMap = arrayTuples .groupBy(_._1)

, кажется, портит порядок.Помощь оценена.

РЕДАКТИРОВАТЬ: Ввести порядок первого столкновения.

Ответы [ 3 ]

5 голосов
/ 25 апреля 2019

Вы можете использовать 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 в конец, я решил foldRight, что перемещает запись A в конец, а затем foldRight снова, чтобы полностью изменить все это.

3 голосов
/ 25 апреля 2019

Вы можете получить вставленную упорядоченную карту следующим образом:

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 голосов
/ 25 апреля 2019

По умолчанию 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...