user8719628
user8719628

Reputation:

Fetch the sum of values for certain keys from a Map [Scala]

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

Answers (3)

Oleg Pyzhcov
Oleg Pyzhcov

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

Dima
Dima

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

jwvh
jwvh

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

Related Questions