Reputation: 8431
New to scala .. I wanted to calculate the sum of all elements in List which is a value of a map.
case class Test(shareClass:String, noOfShares:Long){}
val list = new Test("a", 10)::new Test("b",20)::new Test("a",30)::new Test("b", 5)::Nil
I wanted to creates a Map of
a -> 40
b -> 25
I understand I can use group by on the list which will give me a list of test values, but I am not sure how to operate on that.
Thanks!
Upvotes: 3
Views: 5007
Reputation: 6711
Using groupBy
creates a Map
where the values are a list of all matching objects:
scala> list.groupBy(_.shareClass)
res0: scala.collection.immutable.Map[String,List[Test]] = Map(b -> List(Test(b,20), Test(b,5)), a -> List(Test(a,10), Test(a,30)))
From there you can use mapValues
to transform the values of the map, first selecting the noOfShares
attribute and then sum
these:
scala> list.groupBy(_.shareClass).mapValues(_.map(_.noOfShares).sum)
res1: scala.collection.immutable.Map[String,Long] = Map(b -> 25, a -> 40)
Note that mapValues
only creates a view on the original Map
, this means the _.map(_.noOfShares).sum
-part is applied every time the result is accessed (even when assigning it to a val
before). To get a plain Map
with only the result, you can call view.force
on it:
scala> list.groupBy(_.shareClass).mapValues(_.map(_.noOfShares).sum).view.force
res2: scala.collection.immutable.Map[String,Long] = Map(b -> 25, a -> 40)
Upvotes: 7
Reputation: 9698
Here you go.
case class Test(shareClass: String, noOfShares: Long) {}
val list = new Test("a", 10) :: new Test("b", 20) :: new Test("a", 30) :: new Test("b", 5) :: Nil
val list2 = list.groupBy((_.shareClass))
.map({ case (a, b) => (a, b.map(_.noOfShares).sum) })
println((list2)) // Map(b -> 25, a -> 40)
Upvotes: 4
Reputation: 483
case class Test(shareClass: String, noOfShares: Long) {}
val list = Test("a", 10) :: Test("b", 20) :: Test("a", 30) :: Test("b", 5) :: Nil
println(list.groupBy(_.shareClass).map(test => (test._1 -> test._2.foldLeft(0L)((o, n) => o + n.noOfShares))))
first, you create groups with groupBy like this:
Map(b -> List(Test(b,20), Test(b,5)), a -> List(Test(a,10), Test(a,30)))
after that you convert the element's values to the sum of Test's noOfShares
Upvotes: 0