scala - GroupBy 多列作为键并对多列求和,如 sql?
问题描述
我正在使用 scala 2.12。
我有一个案例类如下:
case class MyClass(date: java.util.Date, book: String, priceLocal: Double, priceConv: Double)
我可以根据日期和书籍进行分组。
例如,对于:
val listOfMyClass = List(
MyClass(20190708, "book1", 100, 120),
MyClass(20190708, "book1", 200, 220),
MyClass(20190708, "book2", 50, 60),
MyClass(20190708, "book2", 60, 70)
)
val groupedData = listOfMyClass.groupBy(t => (t.date, t.book))
我想要 SQL 中的数据:
(20190708, "book1", 300, 340)
(20190708, "book2", 110, 130)
我能够对一列进行映射和求和,但不能同时使用这两列。
val groupedDataSum = listOfMyClass.groupBy(t => (t.date, t.book)).mapValues(_.map(_.priceLocal).sum)
但是如何将第二列也用作总和?
解决方案
您可以混合使用groupBy
(按日期和书籍对元素进行分组),并reduce
累积分组值:
// val list = List(
// MyClass(Date(2019, 7, 8), "book1", 100, 120),
// MyClass(Date(2019, 7, 8), "book1", 200, 220),
// MyClass(Date(2019, 7, 8), "book2", 50, 60),
// MyClass(Date(2019, 7, 8), "book2", 60, 70)
// )
list
.groupBy { case MyClass(date, book, _, _) => (date, book) }
.mapValues { values =>
values
.map { case MyClass(_, _, priceLocal, priceConv) => (priceLocal, priceConv) }
.reduce((x, y) => (x._1 + y._1, x._2 + y._2))
}
.map { case ((date, book), (priceLocal, priceConv)) =>
(date, book, priceLocal, priceConv)
}
// List(
// (Date(2019, 7, 8), "book1", 300, 340),
// (Date(2019, 7, 8), "book2", 110, 130)
// )
这个:
按日期和书籍分组字符 (
groupBy
)通过以下方式映射每个分组值 (
mapValues
):- 将值映射为价格元组
- 并通过逐部分求和来减少这些元组
将元组 (date, book) 映射到元组 (price, price) 到 4 个元素的元组
推荐阅读
- angular - Angular 7:在 ngoninit 方法上使用 [(ngModel)] 检查复选框
- docker - nfs 不支持“overlay2”” storage-driver=overlay2
- javascript - 将内容添加到其他页面的按钮
- java - Java中默认方法中的默认关键字是可选说明符吗?
- c++ - 在 OSX 上编译 C++ 时找不到库
- oracle - oracledb_exporter 二进制文件
- c++ - C++ 使用来自 CRTP 模板模板基类的构造函数
- google-compute-engine - 用于 kms 的 Python 身份验证
- python - 是否可以通过训练小数据子集来验证深度学习模型?
- r - 在 R 的列表中创建序列