Добавление элемента в конец списка в Scala

223

Звучит как глупый вопрос, но все, что я нашел в интернете, это мусор. Я просто не могу добавить элемент типа Tв список List[T]. Я пытался с, myList ::= myElementно кажется, что это создает странный объект и доступ к myList.lastвсегда возвращает первый элемент, который был помещен в список.

Masiar
источник

Ответы:

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

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

Обратите внимание, что эта операция имеет сложность O (n). Если вам нужна эта операция часто или для длинных списков, рассмотрите возможность использования другого типа данных (например, ListBuffer).

Landei
источник
7
Там нет O (2 * n), постоянные факторы игнорируются для асимптотических сложностей. Я думаю , что Listпреобразуется в ListBufferэлемент добавляется, и ListBufferпреобразованный назад (довольно много , как Stringи StringBuilderв Java), но это только предположение.
Landei
2
Это O (n), потому что вы должны полностью пройти список, чтобы достичь последнего указателя элемента и иметь возможность добавить элемент, указывающий на него последний указатель элемента.
Писарук
39
@ pisaruk, если бы это было так, можно было просто держать указатель на голову и хвост. Однако список в scala является неизменным, что означает, что для «изменения» последнего элемента списка необходимо сначала сделать его копию. Это копия O (n), а не обход самого списка.
2
Я считаю, что это O (n) просто потому, что создает новый список
Раффаэле Росси
3
Оператор cons имеет сложность O (1), так как работает на «предполагаемой» стороне списка.
Landei
67

Это потому, что вы не должны делать это (по крайней мере, с неизменным списком). Если вам действительно нужно добавить элемент в конец структуры данных, и эта структура данных действительно должна быть списком, и этот список действительно должен быть неизменным, тогда сделайте следующее:

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

или это:

List(1,2,3) ::: List(4)
agilesteel
источник
Большое спасибо! Это было именно то, что я искал. Я думаю, из твоего ответа я не должен этого делать, хотя ... Я пересмотрю свою структуру и посмотрю, что я могу сделать. Еще раз спасибо.
Масиар
6
@Masiar используйте Vector, если вы хотите неизменности и эффективного добавления. См. Раздел характеристик производительности в scala-lang.org/docu/files/collections-api/collections.html
Арджан Блокзейл,
29
«Построить список, добавив и затем перевернув его», - это полезный шаблон, если у вас есть много элементов, которые нужно добавить, но я не думаю, что было бы неплохо применять его так, как вы это делаете в случае добавления одного элемента к существующий список. Трюк с «двойным обратным ходом» перестраивает список дважды, в то время :+как , несмотря на неэффективность, он перестраивается только один раз.
Николас Пайетт
25

Списки в Scala не предназначены для изменения. На самом деле, вы не можете добавлять элементы в Scala List; это неизменяемая структура данных , похожая на строку Java. Что вы действительно делаете, когда «добавляете элемент в список» в Scala, так это создаете новый список из существующего списка . (Источник)

Вместо того, чтобы использовать списки для таких случаев использования, я предлагаю использовать 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)
Venkat
источник
2

Мы можем добавить или добавить два списка или список и массив
.

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