12

想定元本と通貨の 2 つのパラメーターを含むオブジェクトのリストから始めて、通貨ごとの想定元本の合計を集計するにはどうすればよいでしょうか?

与えられた:

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")
)

どうすれば入手することができますか:

Map(JPY -> 10000100, USD -> 10010000, GBP -> 10001000)
4

3 に答える 3

17

トランクを使用する場合、機械はすでにそこにあります。groupBy は Traversable で定義されており、sum はリストに直接適用できます。フォールドを記述する必要はありません。

scala> trades groupBy (_.currency) map { case (k,v) => k -> (v map (_.amount) sum) }
res1: Iterable[(String, Int)] = List((GBP,10001000), (JPY,10000100), (USD,10010000))
于 2009-06-22T22:22:28.680 に答える
4

私は単純な group-by 操作 (実際にはGroupable traitからの暗黙的な変換を伴うIterable) を書きました。これにより、取引を によってグループ化できます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 } 

非常に単純なmapElements( mmis a Map) と a foldLeft(または-コレクションに対して非常に簡潔な集計を可能にするため、演算子を/:理解する価値があります) を実行して、合計を取得できるようになりました。foldLeft

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

最後の行に誤りがありましたら、お詫び申し上げます。は(もちろん)tsの値です。mmIterable[Trade]

于 2009-06-21T13:53:53.457 に答える