【问题标题】:Scala groupBy + mapValues + map back to initial format. Is there a better wayScala groupBy + mapValues + 映射回初始格式。有没有更好的办法
【发布时间】:2017-02-03 11:15:40
【问题描述】:

在我正在进行的项目中,我经常发现自己在执行以下模式。

给定一个案例类 X(a: A, b: B, c:C, d: Int),以及一个此类 X 的 xs 的列表:List[X], 我想做数据库相当于按 a、b、c 分组,同时按 d 求和,返回类型为 List[X]。

我通常最终会做的是

xs.groupBy{case X(a,b,c,d) => (a,b,c)).mapValues(_.sum).map(((a,b,c),d)) => X(a,b,c,d))

我的问题是,使用 scala 标准库或 Scalaz 是否有更好/更清晰/更惯用的方法(如果 d 可能是带有 Monoid 实例的任意类型)?

【问题讨论】:

  • 你能发布示例列表和示例输出吗?我不确定你想在这里实现什么目标?
  • 稍后会做
  • 你可能想看看这个 scalaz 例子:stackoverflow.com/questions/7142514/…
  • 就我而言,没有简单的方法可以在“地方”执行分组和映射(不需要中间集合)。 scala 集合上也缺少“zipWith”功能。也许将来会添加它们(java 流允许通过收集器与映射进行分组,但任何使用它们的人都会同意它们的用法不直观)

标签: scala


【解决方案1】:

我想我知道你想要实现什么,我找到了一种更短的方法来实现这一点,你不必使用 mapValues,然后使用 map,而是可以用一张地图完成所有事情,如下所示:

case class X(a: String, b: String, c: String, d: Int){
  def +(that: X) = X(a,b,c, d+that.d)
}

val list = List(X("1","2","3",4),X("1","2","3",5),X("11","22","33",6),X("11","22","33",9))

list.groupBy{
  case X(a,b,c,d) => (a,b,c)}.map{ case (k,v) => X(k._1, k._2, k._3, v.reduce(_ + _).d)}

如果你可以在你的类中使用 sum,它会更短更简洁,但 reduce 也不是那么糟糕。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-16
    相关资源
    最近更新 更多