par*_*rkr 11 functional-programming scala scala-collections
从包含两个参数名义和货币的对象列表开始,我如何汇总每种货币的总名义?
鉴于:
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")
)
Run Code Online (Sandbox Code Playgroud)
我怎样才能得到:
Map(JPY -> 10000100, USD -> 10010000, GBP -> 10001000)
Run Code Online (Sandbox Code Playgroud)
psp*_*psp 16
如果你使用行李箱,机器就已存在.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))
Run Code Online (Sandbox Code Playgroud)
我编写了一个简单的分组操作(实际上Groupable
trait
是从 an 进行隐式转换的a 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
}
Run Code Online (Sandbox Code Playgroud)
因此Groupable
,只需提供一种从 an 中的每个项目中提取密钥Iterable
的方法,然后将具有相同密钥的所有此类项目分组即可。所以,就你而言:
//mm is a MultiMap[Currency, Trade]
val mm = trades groupBy { _.currency }
Run Code Online (Sandbox Code Playgroud)
现在,您可以执行非常简单的mapElements
( mm
is a Map
) 和 a foldLeft
(or /:
- 非常值得理解该foldLeft
运算符,因为它可以对集合进行极其简洁的聚合) 来获取总和:
val sums: Map[Currency, Int] = mm mapElements { ts =>
(0 /: ts) { (sum,t) => sum + t.notional }
}
Run Code Online (Sandbox Code Playgroud)
如果我在最后一行犯了一些错误,我深表歉意。ts
是 的值mm
,(当然)是Iterable[Trade]
。
归档时间: |
|
查看次数: |
9500 次 |
最近记录: |