Додавання елемента до кінця списку в Scala


223

Це звучить як дурне запитання, але все, що я знайшов в Інтернеті, - це сміття. Я просто не можу додати елемент типу Tдо списку List[T]. Я спробував, myList ::= myElementале, схоже, це створює дивний об'єкт і доступ до myList.lastзавжди повертає перший елемент, який був поміщений всередину списку.

Відповіді:


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

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

Зауважимо, що ця операція має складність O (n). Якщо вам потрібна ця операція часто або для довгих списків, подумайте про використання іншого типу даних (наприклад, ListBuffer).


7
Немає O (2 * n), постійні фактори ігноруються для асимптотичних складностей. Я думаю, що Listперетворюється на a ListBuffer, додається елемент і ListBufferповертається назад (майже як Stringі StringBuilderв Java), але це лише здогадка.
Ландей

2
Це O (n), тому що ви повинні повністю пройти список, щоб дістатися до останнього вказівника елемента і мати змогу додавати елемент, вказуючи на нього останній вказівник елемента.
писарук

39
@pisaruk як би це було, можна було просто підтримувати вказівник на голову та хвіст. Однак список у масштабі Scala є непорушним, це означає, що для "модифікації" останнього елемента списку потрібно спершу зробити його копію. Його копія, яка є O (n) - не обхід самого списку.

2
Я вважаю, що це O (n) просто тому, що створює абсолютно новий список
Raffaele Rossi

3
Оператор мінусів має складність O (1), оскільки він працює на "призначеній" стороні списку.
Ландей

67

Це тому, що ви не повинні цього робити (принаймні, зі змінним списком). Якщо вам дійсно потрібно додати елемент до кінця структури даних, і ця структура даних дійсно справді повинна бути списком, і цей список дійсно повинен бути незмінним, тоді зробіть це так:

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

або що:

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

Дуже дякую! Це саме те, що я шукав. Я думаю, що з вашої відповіді я не повинен цього робити ... Я перегляну свою структуру і побачу, що я можу зробити. Знову дякую.
Масіар

6
@Masiar використовуйте вектор, якщо ви хочете незмінність та ефективне додавання. Дивіться розділ характеристик продуктивності на сайті scala-lang.org/docu/files/collections-api/collections.html
Arjan Blokzijl

29
"Створити список заздалегідь, а потім повернути його назад" є корисною схемою, якщо у вас є багато елементів, які потрібно додати, але я не думаю, що це гарна ідея застосовувати його, як ви робите у випадку додавання одного елемента до існуючий список. Трюк "подвійний зворотний" відновлює список удвічі, тоді як :+, неефективний, як це може бути, відновить його лише один раз.
Nicolas Payette

25

Списки Scala не можуть бути змінені. Насправді ви не можете додати елементи до Scala List; це незмінна структура даних , як Java String. Те, що ви насправді робите, коли ви "додаєте елемент до списку" в 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)

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.