문제

두 개의 매개 변수와 통화가 포함 된 객체 목록으로 시작하여 어떻게 통화 당 총 명목상을 집계 할 수 있습니까?

주어진:

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)
도움이 되었습니까?

해결책

나는 간단한 그룹 바이 운영을 썼습니다 (실제로 a Groupable trait an의 암시 적 변환 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 추출하는 방법을 단순히 제공하는 것입니다 열쇠 An의 각 항목에서 Iterable 그런 다음 동일한 키를 가진 모든 항목을 그룹화합니다. 따라서 귀하의 경우 :

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

이제 아주 간단하게 할 수 있습니다 mapElements (mm a Map) 그리고 a foldLeft (또는 /: - 이해할 가치가 있습니다 foldLeft 연산자는 컬렉션을 통해 매우 간결한 집계를 가능하게 할 수 있으므로) : 합계를 얻을 수 있습니다.

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

마지막 줄에서 실수를 저지른 경우 사과드립니다. ts 값입니다 mm, (물론) Iterable[Trade].

다른 팁

트렁크를 사용하면 기계가 이미 있습니다. Groupby는 트래버스 가능에 정의되어 있으며 합계를 목록에 직접 적용 할 수 있으므로 접을 필요가 없습니다.

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)

  • mapS 그룹의 금액에 그룹화 된 값 (그룹의 맵 부분지도줄이다)

  • reduces 값 (_ + _) 합산함으로써 (GroupMap의 일부를 줄입니다줄이다).

이것은 동등한 버전입니다 한 번의 패스로 수행됩니다 목록을 통해 :

trades.groupBy(_.currency).mapValues(_.map(_.amount).reduce(_+_))
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top