如何以更有效和优化的方式从地图中获取某些键的值之和?
例如:
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)
但是寻找比这更好的实现。
任何帮助都非常高兴!
答案 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
}