SCALA - заставить groupBy + sum находить столбцы с нулями - PullRequest
0 голосов
/ 30 сентября 2019

Название вопроса, вероятно, сбивает с толку, так что, надеюсь, мой пример кода будет иметь больше смысла.

Но в принципе, если бы я группировал по набору значений, если это значение не появилось всписок, это не признается. В приведенном ниже примере я пытался найти способ заставить группу распознать, что существует три варианта группирования имен. Но в месяце "2" Фрэнк не появляется, поэтому он не входит в группу.

Я просматривал документы Scala, пытаясь найти способ пройти в список "группы". ценностями ", но я не уверен, существует ли он.

Буду признателен за любые советы о том, как с этим справиться!

Кроме того, к вашему сведению, первое ТАК сообщение, извините, если я что-то забыл. Кроме того, я новичок в Scala, поэтому некоторые из приведенного ниже кода могут быть уродливы, чтобы посмотреть на

(Использование Scala 2.13.1)

ПРИМЕРНЫЙ КОД:

case class Sale (
  month: String,
  name: String,
  amt: Double
)

val sales: List[Sale] = List(
          Sale("1","Bob",12),
          Sale("1","Bob",15),
          Sale("1","Frank",20),
          Sale("1","Joe",10),
          Sale("2","Bob",5),
          Sale("2","Joe",10)
        )

sales.groupBy(_.month).map { case (month, monthSales) => 
  monthSales.groupBy(_.name).map { case (name, nameSales) =>
    val totalSales = nameSales.map(_.amt).sum
        println(s"$month $name $totalSales")
  }
}

ВЫХОД:

2 Bob 5.0
2 Joe 10.0
1 Bob 27.0
1 Joe 10.0
1 Frank 20.0

Желаемый выход:

2 Bob 5.0
2 Joe 10.0
2 Frank 0.0
1 Bob 27.0
1 Joe 10.0
1 Frank 20.0

Ответы [ 2 ]

1 голос
/ 30 сентября 2019

Вот как бы я поступил об этом.

//quick lookup of sales totals
val salesMap = sales.groupMapReduce(s => (s.month,s.name))(_.amt)(_+_)
                    .withDefaultValue(0.0)

//all months and all names
val (months,names) = sales.foldLeft((Set.empty[String], Set.empty[String])) {
  case ((mons,nams), sale) => (mons+sale.month, nams+sale.name)
}

//make report
for {
  mn <- months
  nm <- names
} println(s"$mn, $nm, ${salesMap((mn,nm))}")
//1, Bob, 27.0
//1, Frank, 20.0
//1, Joe, 10.0
//2, Bob, 5.0
//2, Frank, 0.0
//2, Joe, 10.0
1 голос
/ 30 сентября 2019

Когда вы группируете, вы теряете контекст полного набора имен. Вы должны отслеживать все имена и сопоставлять их с продажами, которые у вас есть, если вы хотите их распечатать. Есть много способов сделать это. Вот один из них:

case class Sale (month: String, name: String, amt: Double)

val sales: List[Sale] = List(
  Sale("1","Bob",12),
  Sale("1","Bob",15),
  Sale("1","Frank",20),
  Sale("1","Joe",10),
  Sale("2","Bob",5),
  Sale("2","Joe",10)
)

//Note: view is only for performance enhancements. See https://docs.scala-lang.org/overviews/collections/views.html

val names: Set[String] = sales.view.groupBy(_.name).mapValues(_.head.name).values.toSet

val salesByMonthByName: Map[String, Set[(String, Double)]] = sales
  .groupBy(_.month)
  .mapValues { monthlySales =>
    val salesByPerson = monthlySales
      .groupBy(_.name)
      .mapValues(singlePersonSales => singlePersonSales.view.map(_.amt).sum)
    names.map(name => name -> salesByPerson.getOrElse(name, 0.0))
  }

salesByMonthByName.foreach { case (month, salesByName) =>
    salesByName.foreach { case (name, totalSales) => println(s"$month $name $totalSales") }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...