gpt4 book ai didi

Scala groupBy + mapValues 与 groupBy + map + BreakOut

转载 作者:行者123 更新时间:2023-12-01 19:03:44 24 4
gpt4 key购买 nike

假设我有这样的数据:

scala> case class Foo(a: Int, b: Int)
defined class Foo

scala> val data: List[Foo] = Foo(1,10) :: Foo(2, 20) :: Foo(3,30) :: Nil
data: List[Foo] = List(Foo(1,10), Foo(2,20), Foo(3,30))

我知道在我的数据中,不会有具有相同字段 a 值的 Foo 实例 - 我想将其转换为 Map[Int, Foo] (我不需要 Map[Int, List[Foo]])

我可以:

 scala> val m: Map[Int,Foo] = data.groupBy(_.a).mapValues(_.head)
m: Map[Int,Foo] = Map(2 -> Foo(2,20), 1 -> Foo(1,10), 3 -> Foo(3,30))

或者:

scala> val m: Map[Int,Foo] = data.groupBy(_.a).map(e => e._1 -> e._2.head)(collection.breakOut)
m: Map[Int,Foo] = Map(2 -> Foo(2,20), 1 -> Foo(1,10), 3 -> Foo(3,30))

我的问题:

1) 如何使 breakOut 的实现更加简洁/惯用?

2) 在上述两个解决方案中,我应该注意哪些“幕后”问题? IE。隐藏的内存/计算成本。特别是,我正在寻找对 breakOut 的“外行”解释,该解释不一定涉及对 map 签名的深入讨论。

3)还有我应该注意的其他解决方案(包括使用 ScalaZ 等库)吗?

最佳答案

1) 正如@Kigyo 所指出的,鉴于没有重复的 a,正确的答案不会使用 groupBy:

val m: Map[Int,Foo] = data.map(e => e.a -> e)(breakOut)

当可能存在重复的 a 时,使用 groupBy 很好,但考虑到您的问题,完全没有必要。

2) 首先,如果您计划多次访问值,请不要使用 mapValues.mapValues 方法不会创建新的 Map(与 .map 方法不同)。相反,它会创建一个 Map 的 View ,每次访问该函数时都会重新计算该函数(在您的情况下是_.head)。如果您计划访问很多东西,请考虑使用 map{case (a,b) => a -> ??}

其次,将 breakOut 函数作为 CanBuildFrom 参数传递不会产生额外成本。原因是 CanBuildFrom 参数始终存在,只是有时它是隐式的。真正的签名是这样的:

def map[B, That](f: (A) ⇒ B)(implicit bf: CanBuildFrom[List[A], B, That]): That

CanBuildFrom 的目的是告诉 scala 如何从映射结果(这是 B 的集合)中生成一个 That >s)。如果您省略 breakOut,那么它会使用隐式 CanBuildFrom,但无论哪种方式,都必须有一个 CanBuildFrom,以便有某个对象能够从 B 中构建 That

最后,在 breakOut 的示例中,breakOut 是完全多余的,因为 groupBy 生成一个 Map,因此,Map 上的 .map 默认情况下会返回一个 Map

val m: Map[Int,Foo] = data.groupBy(_.a).map(e => e._1 -> e._2.head)

关于Scala groupBy + mapValues 与 groupBy + map + BreakOut,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24588674/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com