Starting with a list of objects containing two parameters notional and currency, how can I aggregate the total notional per currency?
Given:
case class Trade(name: String, amount: Int, currency: String)
val trades = List(
Trade("T150310", 10000000, "GBP"),
Trade("T150311", 10000000, "JPY"),
Trade("T150312", 10000000, "USD"),
Trade("T150313", 100, "JPY"),
Trade("T150314", 1000, "GBP"),
Trade("T150315", 10000, "USD")
)
How can I get:
Map(JPY -> 10000100, USD -> 10010000, GBP -> 10001000)
Starting Scala 2.13
, most collections are provided with the groupMapReduce method which is (as its name suggests) an equivalent (more efficient) of a groupBy
followed by mapValues
and a reduce step:
trades.groupMapReduce(_.currency)(_.amount)(_ + _)
// immutable.Map[String,Int] = Map(JPY -> 10000100, USD -> 10010000, GBP -> 10001000)
This:
group
s elements based on their currency (group part of groupMapReduce)
map
s grouped values to their amount (map part of groupMapReduce)
reduce
s values (_ + _
) by summing them (reduce part of groupMapReduce).
This is an equivalent version performed in one pass through the List of:
trades.groupBy(_.currency).mapValues(_.map(_.amount).reduce(_+_))
If you use trunk the machinery is already there. groupBy is defined on Traversable and sum can be applied directly to the list, you don't have to write a fold.
scala> trades groupBy (_.currency) map { case (k,v) => k -> (v map (_.amount) sum) }
res1: Iterable[(String, Int)] = List((GBP,10001000), (JPY,10000100), (USD,10010000))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With