创建Scala列表的首选方法

agi*_*all 116 scala

有几种方法可以在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)
}
Run Code Online (Sandbox Code Playgroud)

Dan*_*ral 108

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

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

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

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

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

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

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

  • @KevinMeredith是的.追加为O(n),前置为O(1). (2认同)

小智 65

对于简单的情况:

val list = List(1,2,3) 
Run Code Online (Sandbox Code Playgroud)

:)

  • 不要忘记cons运营商!1 :: 2 :: 3 ::无 (10认同)
  • 或者我应该说"运营商"? (3认同)

Ale*_*rov 22

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

def listTestD = (0 to 3).toList
Run Code Online (Sandbox Code Playgroud)

要么

def listTestE = for (i <- (0 to 3).toList) yield i
Run Code Online (Sandbox Code Playgroud)


Jas*_*onG 5

您希望通过消除任何变量来关注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)
Run Code Online (Sandbox Code Playgroud)

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

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

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

scala> list.foldLeft(0)(_+_)
res0: Int = 55
Run Code Online (Sandbox Code Playgroud)