Додавання елемента до кінця списку в 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.