【问题标题】:Scala most efficient operator to add to a listScala 最高效的添加到列表的运算符
【发布时间】:2015-09-13 14:34:54
【问题描述】:

通过增量修改来构建一个 scala 列表。什么是最有效的“添加”运算符?在 CPU 和资源消耗方面。

例如,我们想从 List(1,2,3) 创建一个由连续数字组成的元组列表。结果是: List((1,2), (2,3))

方法 1 - 使用 :+ 运算符

def createConsecutiveNumPair1[T](inList: List[T]) : List[(T, T)] = {
  var listResult = List[(T, T)]()
  var prev = inList(0)
  for (curr <- inList.tail)
  {
    listResult = listResult :+ (prev, curr)
    prev = curr
  }
  listResult
}

方法 2 - 使用 ::= 运算符

def createConsecutiveNumPair2[T](inList: List[T]) : List[(T, T)] = {
  var listResult = List[(T, T)]()
  var prev = inList(0)
  for (curr <- inList.tail)
  {
    listResult ::= (prev, curr)
    prev = curr
  }
  listResult
}

测试

scala> val l1 = List(1,2,3)
l1: List[Int] = List(1, 2, 3)

scala> createConsecutiveNumPair1(l1)
res77: List[(Int, Int)] = List((1,2), (2,3))

scala> createConsecutiveNumPair2(l1)
res78: List[(Int, Int)] = List((2,3), (1,2))

问题:哪个算子的CPU、资源消耗最低?如果您能提出一种更好的 scala 方法来重写上述方法,也将不胜感激。

【问题讨论】:

    标签: scala


    【解决方案1】:

    这些方法通常只是相互调用(尽管请检查实现以确保确定)。 List 是一个单链表,针对访问头部而不是尾部进行了优化,因此将元素添加到前面而不是末尾更有效。如果要访问/添加列表末尾的元素,最好使用Vector

    (与往常一样,如果您要问这个问题,您应该拥有能够告诉您答案的自动化工具。如果您没有使用分析器来告诉您应用程序的哪些部分运行缓慢,那就是不值得花时间在这种微优化上——你几乎肯定是在优化错误的部分)。

    【讨论】:

    • 说得好“花时间在这种微优化上是不值得的——你几乎肯定是在优化错误的部分”。除非你要处理一个非常大的列表。
    • @Imm,感谢您的宝贵建议。您能否为 Scala 推荐一个分析工具(并且可能也可以测试 Spark)?
    • 我使用 JProfiler - 它很贵但非常值得 IMO。我知道可以在 JProfiler 下运行 Hadoop/yarn 作业,这也可以让您分析 spark 代码,但我没有任何直接经验。
    【解决方案2】:

    您的第一个代码的问题在于它附加了O(n) on List。所以算法基本上是O(n^2)

    添加List 非常有效,因为它以恒定时间O(1) 运行,您在第二个算法中执行此操作。您可以使用它并在最后执行reverse 以使两种方法的结果相等,这大致使其在O(n) 中运行。

    但是,库中已经有一个很好的方法可以满足您的需求。 sliding 是您正在寻找的。滑动的参数定义了元组的大小。

    这会给你一个List[List[Int]]

    List(1,2,3,4).sliding(2).toList  //List(List(1,2), List(2,3), List(3,4))
    

    如果你坚持使用元组,你可以额外使用collectmap。请注意,当列表只有一个元素时,map 会抛出异常。

    List(1,2,3,4).sliding(2).collect{
      case List(a,b) => (a,b)
    }.toList                        //List((1,2), (2,3), (3,4))
    

    【讨论】:

    • sliding方法的信息很有帮助。
    • @Kigyo 感谢您对复杂性的解释。现在我更好地理解了List Scala Doc 中关于这些运算符的细微差别。感谢滑动。很高兴知道。
    猜你喜欢
    • 2012-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-20
    • 1970-01-01
    • 2013-09-18
    • 2015-11-01
    • 1970-01-01
    相关资源
    最近更新 更多