从Map [Scala]中获取某些键的值的总和

时间:2017-10-04 21:25:48

标签: algorithm scala dictionary key-value

如何以更有效和优化的方式从地图中获取某些键的值之和?

例如:

var myMap = "SOSSPSSQSSOR".groupBy(identity).mapValues(_.size).toMap
>>myMap: scala.collection.immutable.Map[Char,Int] = Map(Q -> 1, P -> 1, R -> 1, O -> 2, S -> 7)

myMap.sumExcludingValuesFor("S,O")

def sumExcludingValuesFor(s:String):Int = {
//return the sum of the values for keys except S, O
}

到目前为止我的实施:

var charMap = "SOSSPSSQSSOR".toString.groupBy(identity).mapValues(_.size).toMap
var excludeChar = Set('S','O')
var mapExcludingSO = charMap.filterKeys { excludeChar.contains(_) == false }
println(mapOnlySO.values.toList.sum)

但是寻找比这更好的实现。

任何帮助都非常高兴!

3 个答案:

答案 0 :(得分:2)

一个经常被忽视的事实是您可以将Scala集合用作函数。

  • Seq[A]Int => A(部分,按索引)
  • Set[A]A => Boolean(会员资格检查)
  • Map[K, V]K => V(部分)

允许你写:

myMap.keysIterator.filterNot("SO".toSet).map(myMap).sum

它还可以避免使用基于Iterator的中间集合

答案 1 :(得分:0)

一旦您隔离了感兴趣的密钥,而不是使用它们构建新的Map,请使用它们直接访问要汇总的值。

val charMap = "SOSSPSSQSSOR".groupBy(identity).mapValues(_.length)
charMap.keySet.diff("SO".toSet).foldLeft(0)(_ + myMap(_)) // res0: Int = 3

答案 2 :(得分:0)

您的实施很好。你可以通过消除中间集合,以及一些不必要的遍历和密钥查找来获得边际改进,但这对于几乎所有实际目的来说都是一种过度杀伤:

input
  .groupBy(identity)
  .foldLeft(0) { 
     case (s, ("S"|"O", _)) => s
     case (s, (_, v)) => s + v.size
  }