Reputation:
How to get the sum of values of certain keys from a map in a more efficient and optimised way?
For example:
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
}
My implementation so far:
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)
But looking for a better implementation than this.
Any help is highly apprecaited!
Upvotes: 0
Views: 174
Reputation: 7353
One often overlooked fact is that you can use Scala collections as a functions.
Seq[A]
is Int => A
(partial, by index)Set[A]
is A => Boolean
(membership check)Map[K, V]
is K => V
(partial)Allowing you to write:
myMap.keysIterator.filterNot("SO".toSet).map(myMap).sum
It will also avoid intermediate collections, being Iterator
-based
Upvotes: 2
Reputation: 40500
Your implementation is fine. You could, probably, get a marginal improvement by eliminating intermediate collections, and a few unnecessary traversals and key lookups, but this would be an overkill for pretty much all practical purposes:
input
.groupBy(identity)
.foldLeft(0) {
case (s, ("S"|"O", _)) => s
case (s, (_, v)) => s + v.size
}
Upvotes: 0
Reputation: 51271
Once you've isolated the keys of interest, instead of building a new Map
with them, use them to directly access the values to be summed.
val charMap = "SOSSPSSQSSOR".groupBy(identity).mapValues(_.length)
charMap.keySet.diff("SO".toSet).foldLeft(0)(_ + myMap(_)) // res0: Int = 3
Upvotes: 0