在Scala中将元素追加到列表的末尾


223

这听起来像一个愚蠢的问题,但是我在互联网上发现的只是垃圾。我根本无法将类型的元素添加T到列表中List[T]。我尝试过,myList ::= myElement但似乎它创建了一个奇怪的对象,并且访问myList.last总是返回放置在列表中的第一个元素。

Answers:


394
List(1,2,3) :+ 4

Results in List[Int] = List(1, 2, 3, 4)

注意,该运算的复杂度为O(n)。如果您经常需要此操作,或者需要较长的列表,请考虑使用其他数据类型(例如ListBuffer)。


7
没有O(2 * n),常数因渐进复杂性而被忽略。我认为将List转换为ListBuffer,将元素追加,然后ListBuffer转换回(StringStringBuilderJava中非常相似),但这只是一个猜测。
兰代

2
之所以为O(n),是因为您必须完全遍历列表才能到达最后一个元素指针,并且能够附加使最后一个元素指针指向它的元素。
pisaruk

39
@pisaruk如果是这种情况,则可以保持指向头和尾的指针。但是,scala中列表是不可变的,这意味着要“修改”列表的最后一个元素,需要首先对其进行复制。它是O(n)的副本-而不是列表本身的遍历。

2
我相信它是O(n)仅仅是因为创建了一个全新的列表
Raffaele Rossi 2014年

3
cons运算符的复杂度为O(1),因为它在列表的“预期”侧起作用。
兰代2015年

67

这是因为您不应该这样做(至少使用不可变的列表)。如果您确实确实需要在数据结构的末尾附加一个元素,并且此数据结构确实需要作为一个列表,并且此列表确实必须是不可变的,则可以这样做:

(4 :: List(1,2,3).reverse).reverse

或者那个:

List(1,2,3) ::: List(4)

非常感谢!那正是我要寻找的。我想从您的答案中我不应该这样做……我将修改我的结构,看看该怎么办。再次感谢。
Masiar 2011年

6
如果您想要不可变性和高效的追加,则@Masiar使用Vector。请参阅scala-lang.org/docu/files/collections-api/collections.html中
Blokzijl

29
如果您要添加多个元素,“先添加列表然后反转列表”是一种有用的模式,但是我不认为像在单个元素上添加一个元素那样应用它是一个好主意。现有清单。“双重反向”技巧将列表重建两次,而:+效率低下的列表可能仅重建一次。
Nicolas Payette

25

Scala中的列表并非旨在进行修改。实际上,您不能将元素添加到Scala中List;它是一个不变的数据结构,例如Java String。当您在Scala中“将元素添加到列表”时,实际要做的是从现有List创建一个新List(资源)

建议不要使用ArrayBuffer或来使用此类用例的列表ListBuffer。这些数据结构旨在添加新元素。

最后,在完成所有操作之后,可以将缓冲区转换为列表。请参阅以下REPL示例:

scala> import scala.collection.mutable.ListBuffer
import scala.collection.mutable.ListBuffer

scala> var fruits = new ListBuffer[String]()
fruits: scala.collection.mutable.ListBuffer[String] = ListBuffer()

scala> fruits += "Apple"
res0: scala.collection.mutable.ListBuffer[String] = ListBuffer(Apple)

scala> fruits += "Banana"
res1: scala.collection.mutable.ListBuffer[String] = ListBuffer(Apple, Banana)

scala> fruits += "Orange"
res2: scala.collection.mutable.ListBuffer[String] = ListBuffer(Apple, Banana, Orange)

scala> val fruitsList = fruits.toList
fruitsList: List[String] = List(Apple, Banana, Orange)

3

这类似于答案之一,但方式不同:

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

scala> val y=x:::4::Nil
y: List[Int] = List(1, 2, 3, 4)

2

我们可以添加或添加两个列表,也可以添加list&array
追加:

var l = List(1,2,3)    
l=l:+4 
Result : 1 2 3 4  
var ar = Array(4,5,6)    
for(x<-ar)    
{ l=l:+x}  
  l.foreach(println)

Result:1 2 3 4 5 6

前置:

var l = List[Int]()  
   for(x<-ar)  
    { l=x::l } //prepending    
     l.foreach(println)   

Result:6 5 4 1 2 3

1
是的,我们可以,但是由于其他答案中提到的所有原因,这将是一个坏主意。
jwvh
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.