Aggregate list values in Scala

前端 未结 3 2018
孤街浪徒
孤街浪徒 2021-02-02 18:08

Starting with a list of objects containing two parameters notional and currency, how can I aggregate the total notional per currency?

Given:

case class T         


        
3条回答
  •  [愿得一人]
    2021-02-02 18:52

    I wrote a simple group-by operation (actually a Groupable trait with an implicit conversion from an Iterable) which would allow you to group your trades by their currency:

    trait Groupable[V] extends Iterable[V] {
      def groupBy(f: V => K): MultiMap[K, V] = {
        val m = new mutable.HashMap[K, Set[V]] with mutable.MultiMap[K, V]
        foreach { v => m add (f(v), v) } //add is defined in MultiMap
        m
      }
    }
    implicit def it2groupable(it: Iterable[V]): Groupable[V] = new Groupable[V] {
      def elements = it.elements
    }
    

    So Groupable is simply providing a way to extract a key from each item in an Iterable and then grouping all such items which have the same key. So, in your case:

    //mm is a MultiMap[Currency, Trade]
    val mm = trades groupBy { _.currency } 
    

    You can now do a quite simple mapElements (mm is a Map) and a foldLeft (or /: - well worth understanding the foldLeft operator as it enables extremely concise aggregations over collections) to get the sum:

    val sums: Map[Currency, Int] = mm mapElements { ts => 
        (0 /: ts) { (sum,t) => sum + t.notional } 
    }
    

    Apologies if I've made some mistakes in that last line. ts are the values of mm, which are (of course) Iterable[Trade].

提交回复
热议问题