【问题标题】:Scala build an arraybuffer of the same length with integersScala用整数构建一个相同长度的arraybuffer
【发布时间】:2013-05-21 14:22:19
【问题描述】:

我有一个ArrayBuffer,我想从中将所有对象转换为它们各自的大小到现有缓冲区:

trait Obj {
  def size: Int
}

def copySizes(input: ArrayBuffer[Obj], output: ArrayBuffer[Int]): Unit = {
  output.clear()
  input foreach { obj =>
    output += obj.size
  }
}

有没有更好的惯用方式来描述 scala 中的 copySizes ? 我在考虑这样的语法:

input.mapTo(_.size, output)

【问题讨论】:

    标签: scala copy arraybuffer


    【解决方案1】:

    你可以

    output ++= input.view.map(_.size)
    

    它具有不可忽略的额外开销(~2x 运行时间)但更紧凑。不过,您可以更紧凑地编写您的版本:

    input.foreach{ output += _.size }
    

    所以我没有理由不使用它。

    【讨论】:

    • @MikaëlMayer - 当然。您希望它在现有缓冲区中!否则你只需input.map(_.size)
    【解决方案2】:

    您是否考虑过尝试使用输出缓冲区作为累加器对输入缓冲区进行 foldLeft 并在函数体中进行追加?

    val output = input.foldLeft(ArrayBuffer[Int]())(_ += _.size)
    

    正如@Rex Kerr 所提到的,与您正在做的foreach 相比,这里的性能可能会受到影响,但我不确定这是一个高性能需求的代码。我想这取决于缓冲区中有多少项目以及该代码被命中的频率。如果它的项目数量很少,或者这不是一段始终被命中的代码,那么你可能会更好地使用功能性更强的东西(折叠)而不是更基于副作用的东西(foreach)。

    通常在编写 Scala 代码时,您必须做出决定;我关心功能纯度/漂亮的scala代码还是需要优化的东西。我尽可能保持纯粹的功能性,然后对我的系统进行性能测试,找到热点并在需要时进行优化。过早的优化是万恶之源(或类似的东西)=)

    【讨论】:

    • 你能举个例子吗?
    • @MikaëlMayer - (output /: input){ _ += _.size },但速度慢了约 4 倍。
    • @Rex Kerr 这是给定折叠的~4x dip,还是您实际上运行了一组样本来衡量折叠对性能的影响?如果采样,输入缓冲区中有多少个样本和多少项?
    • @cmbaxter - 这不是给定的,但它是相当典型的。在这种情况下,我使用 1024 个字符串的数组进行了基准测试。
    • 感谢您的信息。我只是很好奇开销是否是由于折叠中每次迭代的额外函数调用,所以如果 JIT 能够在充分预热的情况下进行优化/内联。
    猜你喜欢
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 2018-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-16
    相关资源
    最近更新 更多