2009-06-21 13 views
10

私はScalaを学び、言語の機能面のいくつかを探っています。Scalaの集計リストの値

想定元と通貨の2つのパラメータを含むオブジェクトのリストから、通貨ごとの合計概念をどのように集計できますか?

//sample data 
val t1 = new Trade("T150310", 10000000, "GBP"); 
val t2 = new Trade("T150311", 10000000, "JPY"); 
val t3 = new Trade("T150312", 10000000, "USD"); 
val t4 = new Trade("T150313", 100, "JPY"); 
val t5 = new Trade("T150314", 1000, "GBP"); 
val t6 = new Trade("T150315", 10000, "USD"); 

val trades = List(t1, t2, t3, t4, t5, t6); 

答えて

4

私は、単純なグループによる操作(Iterableからの暗黙的な変換と実際Groupabletrait)その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 
} 

のでGroupableがあります単にキーIterableの各アイテムから抽出し、同じキーを持つすべてのアイテムをグループ化する方法を提供するだけです。だから、あなたのケースで:

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

あなたは今非常に簡単mapElementsmmMapある)とfoldLeft行うことができます(または/: - それは、コレクションを超える非常に簡潔な集計を可能とfoldLeftオペレータを理解するだけの価値を)します和を得る:

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

私はその最後の行でいくつかの間違いをした場合にお詫び申し上げます。 tsは、mmの値であり、(もちろん)Iterable[Trade]です。

+0

申し訳ありませんが、何らかの理由で私は「トレード」を読んでいますが、私の元の回答では「タプル」と聞いています。私は今編集しました! –

16

トランクを使用している場合、機械は既にそこにあります。 groupByがTraversableで定義されていて、合計をリストに直接適用することができます。折り返しを書く必要はありません。

scala> trades groupBy (_.currency) map { case (k,v) => k -> (v map (_.amount) sum) } 
res1: Iterable[(String, Int)] = List((GBP,10001000), (JPY,10000100), (USD,10010000)) 
+0

それは2.8に入っていますか? –

+0

そして、合計関数がどこから来ているのか説明できますか? –

+0

はい、今はトランクとは何ですか2.8です。 sumメソッドはNumericTraversableOpsに定義されています。これはあなたが知る必要のあるクラスではありませんが、基本的にNumeric [T]の存在に基づいて暗黙的にTraversableにメソッドを追加します。一般的に定義することができます。 – extempore