Scala'daki bir listenin sonuna bir öğe ekleme


224

Kulağa aptalca bir soru gibi geliyor, ama internette bulduğum tek şey çöptü. Sadece türünde bir unsuru ekleyemezsiniz Tbir liste halinde List[T]. Ben denedim myList ::= myElementama garip bir nesne oluşturur ve erişim myList.lasther zaman listenin içine koymak ilk öğe döndürür görünüyor .

Yanıtlar:


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

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

Bu işlemin O (n) karmaşıklığına sahip olduğuna dikkat edin. Bu işleme sık sık veya uzun listelere ihtiyacınız varsa, başka bir veri türü (örn. ListBuffer) kullanmayı düşünün.


7
O (2 * n) yoktur, asimptotik karmaşıklıklar için sabit faktörler göz ardı edilir. Sanırım Listbir dönüştürülür ListBuffer, öğe eklenir ve ListBuffergeri dönüştürülür (hemen hemen benzer Stringve StringBuilderJava'da), ama bu sadece bir tahmin.
Landei

2
O (n) 'dir, çünkü son eleman işaretçisine ulaşmak için listeyi tamamen gezmeniz ve son eleman işaretçisini işaret eden elemanı eklemeniz gerekir.
pisaruk

39
@pisaruk böyleyse, sadece kafaya ve kuyruğa bir işaretçi tutabilirdi. Bununla birlikte, scala'daki liste değişmezdir, yani listenin son öğesini "değiştirmek" için öncelikle bir kopyasını almak gerekir. O (n) olan kopya - listenin kendisinde gezinme değil.

2
O (n) olduğuna inanıyorum çünkü yepyeni bir liste yaratıyor
Raffaele Rossi

3
Eksileri operatörü, listenin "amaçlanan" tarafında çalıştığı için O (1) karmaşıklığına sahiptir.
Landei

67

Çünkü bunu yapmamalısınız (en azından değişmez bir listeyle). Bir veri yapısının sonuna gerçekten gerçekten bir öğe eklemeniz gerekiyorsa ve bu veri yapısının gerçekten bir liste olması gerekiyorsa ve bu liste gerçekten değişmez olmalıdır, o zaman bunu yapın:

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

yada bu:

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

Çok teşekkürler! Tam da aradığım şey buydu. Sanırım cevabınızdan bunu yapmamalıyım ... Yapımı gözden geçireceğim ve neler yapabileceğimi göreceğim. Tekrar teşekkürler.
Masiar

6
@Masiar, değişmezlik ve verimli bir ekleme istiyorsanız bir Vector kullanın. Scala-lang.org/docu/files/collections-api/collections.html
Arjan Blokzijl

29
Eklemek için birçok öğeniz varsa "listeyi ön ekleyerek ve sonra tersine çevirerek oluştur" yararlı bir kalıptır, ancak bir öğeye tek bir öğe ekleme durumunda yaptığınız gibi uygulamak iyi bir fikir değildir. varolan liste. "Çift ters" hile listeyi iki kez yeniden oluştururken :+, verimsiz olduğu gibi yalnızca bir kez yeniden oluşturur.
Nicolas Payette

25

Scala'daki listeler değiştirilmek üzere tasarlanmamıştır. Aslında, bir Scala'ya eleman ekleyemezsiniz List; bir var değişmez veri yapısı bir Java dize gibi. Scala'da "bir listeye öğe eklediğinizde" yaptığınız şey , varolan bir Listeden yeni bir Liste oluşturmaktır . (Kaynak)

Bu tür kullanım durumları için listeler kullanmak yerine, ArrayBufferya a ya da a kullanmanızı öneririm ListBuffer. Bu veri yapıları yeni unsurlar eklenecek şekilde tasarlanmıştır.

Son olarak, tüm işlemleriniz tamamlandıktan sonra, arabellek bir listeye dönüştürülebilir. Aşağıdaki REPL örneğine bakın:

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

Bu, cevaplardan birine benzer ancak farklı bir şekilde:

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

İki liste veya liste ve dizi ekleyebilir veya başa ekleyebiliriz
:

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

prepending:

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

Result:6 5 4 1 2 3

1
Evet, yapabiliriz, ancak diğer cevaplarda belirtilen tüm nedenler için kötü bir fikir olurdu.
jwvh
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.