scala Список кортежей, найдите каждое максимальное значение ключа, не используйте groupBy - PullRequest
0 голосов
/ 31 марта 2020

вот код,

 val arr = List(("A", 1), ("B", 2), ("A", 3), ("B", 1), ("A", 2), ("C", 4), ("B", 5), ("C", 2))
 val res = arr.groupBy(x => x._1).map(x => x._2.maxBy(e => e._2))

получить результат как:

Map(A -> 3, C -> 4, B -> 5)

, но оператор groupby в большом списке кортежей очень медленный , Я хочу использовать другой оператор, такой как foldleft для достижения того же результата, к сожалению, я не могу достичь такой цели.

в моем вопросе scala версия 2.10.5

последняя доля groupby source code

def groupBy[K](f: A => K): immutable.Map[K, Repr] = {
    val m = mutable.Map.empty[K, Builder[A, Repr]]
    for (elem <- this) {
      val key = f(elem)
      val bldr = m.getOrElseUpdate(key, newBuilder)
      bldr += elem
    }
    val b = immutable.Map.newBuilder[K, Repr]
    for ((k, v) <- m)
      b += ((k, v.result))

    b.result
  }

Ответы [ 2 ]

4 голосов
/ 31 марта 2020

Если вы хотите повторить список один раз:

val arr = List(("A", 1), ("B", 2), ("A", 3), ("B", 1), ("A", 2), ("C", 4), ("B", 5), ("C", 2))

val res: mutable.Map[String, Int] = arr.foldLeft(Map.empty[String, Int]) {
  case (acc, (key, value)) =>
    acc.get(key).fold(acc + (key -> value)) { oldValue =>
      acc + (key -> math.max(value, oldValue))
    }
}

Если вам не нужны затраты на выделение неизменяемого `Map [String, Int], вы можете вместо этого использовать изменяемый:

val res: Map[String, Int] = arr.foldLeft(mutable.Map.empty[String, Int]) {
  case (acc, (key, value)) =>
    acc.get(key).fold(acc += (key -> value)) { oldValue =>
      acc += (key -> math.max(value, oldValue))
    }
}
0 голосов
/ 31 марта 2020
arr.foldLeft(collection.mutable.Map.empty[String, Int]) {
  case (map, (k, v)) =>
    map.get(k) match {
      case Some(a) => map(k) = math.max(v, a)
      case _ => map(k) = v
    }
    map
}

Примечание: Используйте mutable.Map, как вы упомянули, размер коллекции большой.

...