質問

想定元本と通貨の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)
役に立ちましたか?

解決

単純なグループ化操作(実際には Iterable からの暗黙的な変換を伴う Groupable trait )を作成しました。 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 の各アイテムから key を抽出する方法を提供し、同じキー。したがって、あなたの場合:

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

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

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

その最後の行で間違いを犯した場合はおAび申し上げます。 ts mm の値で、(もちろん) Iterable [Trade] です。

他のヒント

トランクを使用する場合、機械はすでにそこにあります。 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))

Scala 2.13 以降、ほとんどのコレクションは groupMapReduce メソッド(その名前が示すように) groupBy の後に mapValues およびステップを減らす:

trades.groupMapReduce(_.currency)(_.amount)(_ + _)
// immutable.Map[String,Int] = Map(JPY -> 10000100, USD -> 10010000, GBP -> 10001000)

これ:

  • グループの通貨に基づいた要素( group MapReduceのグループ部分)

  • map の値をその量にグループ化します(グループのマップ部分 Map Reduce)

  • reduce sの値( _ + _ )を合計して(groupMap Reduce の一部を減らします)。

これは同等のバージョンですリストの1つのパスで実行

trades.groupBy(_.currency).mapValues(_.map(_.amount).reduce(_+_))
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top