创建Scala列表的首选方法

scala

106181 观看

10回复

2768 作者的声誉

有几种方法可以在Scala中构造不可变列表(请参阅下面的设计示例代码)。您可以使用可变的ListBuffer,创建var列表并对其进行修改,使用尾递归方法,以及可能还有其他我不了解的方法。

本能地,我使用ListBuffer,但我没有充分的理由这样做。有没有一种首选或惯用的方法来创建列表,还是有一种方法最适合一种方法而不是另一种方法?

import scala.collection.mutable.ListBuffer

// THESE are all the same as: 0 to 3 toList.
def listTestA() ={
    var list:List[Int] = Nil

    for(i <- 0 to 3) 
        list = list ::: List(i)
    list
}


def listTestB() ={
    val list = new ListBuffer[Int]()

    for (i <- 0 to 3) 
        list += i
    list.toList
}


def listTestC() ={
    def _add(l:List[Int], i:Int):List[Int] = i match {
        case 3 => l ::: List(3)
        case _ => _add(l ::: List(i), i +1)
    }
    _add(Nil, 0)
}
作者: agilefall 的来源 发布者: 2009 年 8 月 6 日

回应 (10)


107

255910 作者的声誉

决定

ListBuffer是一个可变列表,具有恒定时间附加和恒定时间转换为List

List 是不可变的,具有常量时间前置和线性时间附加。

如何构建列表取决于您将使用列表的算法以及获取元素的顺序。

例如,如果你按照与使用它们相反的顺序获得元素,那么你可以使用a List和pre prends。无论你是否使用尾递归函数foldLeft,或其他东西都没有真正相关。

如果您使用相同顺序的元素,那么ListBuffer如果性能至关重要,那么a 很可能是一个更好的选择。

但是,如果你不是一个关键路径上和输入足够低,可以随时reverse列表后,或只是foldRight,或reverse输入,这是线性时间。

不要做的是使用一个List,并追加到它。这将使您的性能远远低于最后的前置和后退。

作者: Daniel C. Sobral 发布者: 06.08.2009 08:56

22

10487 作者的声誉

嗯..这些对我来说似乎太复杂了。我可以提议吗?

def listTestD = (0 to 3).toList

要么

def listTestE = for (i <- (0 to 3).toList) yield i
作者: Alexander Azarov 发布者: 06.08.2009 09:00

2

10457 作者的声誉

我总是喜欢List,我在“for comprehension”之前使用“fold / reduce”。但是,如果需要嵌套的“折叠”,则“理解”是优选的。如果我无法使用“fold / reduce / for”完成任务,则递归是最后的手段。

所以对于你的例子,我会这样做:

((0 to 3) :\ List[Int]())(_ :: _)

在我做之前:

(for (x <- 0 to 3) yield x).toList

注意:由于“_”的顺序,我在这里使用“foldRight(:\)”而不是“foldLeft(/ :)”。对于不抛出StackOverflowException的版本,请改用“foldLeft”。

作者: Walter Chang 发布者: 07.08.2009 03:28

65

0 作者的声誉

对于简单的情况:

val list = List(1,2,3) 

:)

作者: Leif 发布者: 07.08.2009 06:36

2

11267 作者的声誉

注意:此答案是针对旧版本的Scala编写的。

Scala集合类将从Scala 2.8开始重新设计,因此请准备好尽快更改创建列表的方式。

什么是创建列表的向前兼容方式?我不知道,因为我还没有读过2.8文档。

PDF文档,描述了集合类的建议更改

作者: André Laszlo 发布者: 07.08.2009 08:22

5

3678 作者的声誉

您希望通过消除任何变量来关注Scala中的不变性。可读性对于你的同伴来说仍然很重要,所以:

尝试:

scala> val list = for(i <- 1 to 10) yield i
list: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

在大多数情况下,您可能甚至不需要转换为列表:)

索引序列将包含您需要的一切:

也就是说,您现在可以处理IndexedSeq:

scala> list.foldLeft(0)(_+_)
res0: Int = 55
作者: JasonG 发布者: 19.03.2013 12:29

1

438 作者的声誉

作为一个新的scala开发人员,我使用上面建议的方法编写了一个小测试来检查列表创建时间 它看起来像(对于(p < - (0到x))产生p)toList最快的方法。

import java.util.Date
object Listbm {

  final val listSize = 1048576
  final val iterationCounts = 5
  def getCurrentTime: BigInt = (new Date) getTime

  def createList[T] ( f : Int => T )( size : Int ): T = f ( size )

  // returns function time execution
  def experiment[T] ( f : Int => T ) ( iterations: Int ) ( size :Int ) : Int  = {

    val start_time = getCurrentTime
    for ( p <- 0 to iterations )  createList ( f ) ( size )
    return (getCurrentTime - start_time) toInt

  }

  def printResult ( f:  => Int ) : Unit = println ( "execution time " + f  )

  def main( args : Array[String] ) {


    args(0) match {

      case "for" =>  printResult ( experiment ( x => (for ( p <- ( 0 to x ) ) yield p) toList  ) ( iterationCounts ) ( listSize ) )
      case "range"  =>  printResult ( experiment ( x => ( 0 to x ) toList ) ( iterationCounts ) ( listSize ) )
      case "::" => printResult ( experiment ( x => ((0 to x) :\ List[Int]())(_ :: _) ) ( iterationCounts ) ( listSize ) )
      case _ => println ( "please use: for, range or ::\n")
    }
  }
}
作者: Yuli Reiri 发布者: 13.10.2013 10:01

2

13613 作者的声誉

List.tabulate像这样使用

List.tabulate(3)( x => 2*x )
res: List(0, 2, 4)

List.tabulate(3)( _ => Math.random )
res: List(0.935455779102479, 0.6004888906328091, 0.3425278797788426)

List.tabulate(3)( _ => (Math.random*10).toInt )
res: List(8, 0, 7)
作者: elm 发布者: 21.07.2014 08:27

0

4195 作者的声誉

只是一个使用collection.breakOut的示例

scala> val a : List[Int] = (for( x <- 1 to 10 ) yield x * 3)(collection.breakOut)
a: List[Int] = List(3, 6, 9, 12, 15, 18, 21, 24, 27, 30)

scala> val b : List[Int] = (1 to 10).map(_ * 3)(collection.breakOut)
b: List[Int] = List(3, 6, 9, 12, 15, 18, 21, 24, 27, 30)
作者: Arne 发布者: 20.07.2016 05:35

0

3967 作者的声誉

要创建字符串列表,请使用以下命令:

val l = List("is", "am", "are", "if")
作者: KayV 发布者: 16.03.2019 06:48
32x32