Scala: Bir Diziye bir öğe eklemenin en iyi yolu nedir?


111

Array[Int]Beğendiğimi söyle

val array = Array( 1, 2, 3 )

Şimdi 4, aşağıdaki örnekte olduğu gibi , diziye bir öğe eklemek istiyorum, değeri söyleyin :

val array2 = array + 4     // will not compile

Elbette System.arraycopy()bunu kendi başıma kullanabilir ve yapabilirim, ancak bunun için bulamadığım bir Scala kütüphanesi işlevi olmalı. Herhangi bir işaret için teşekkürler!

Notlar:

  1. Aşağıdaki satırdaki gibi başka bir öğe dizisi ekleyebileceğimin farkındayım, ancak bu çok yuvarlak görünüyor:

    val array2b = array ++ Array( 4 )     // this works
  2. List vs Array'in avantajlarının ve dezavantajlarının farkındayım ve burada, çeşitli nedenlerle özellikle bir Array'i genişletmekle ilgileniyorum.

Düzenle 1

:+Operatör yöntemine işaret eden cevaplar için teşekkürler . Aradığım şey buydu. Ne yazık ki, özel bir append () yöntemi uygulamasından oldukça yavaştır arraycopy- yaklaşık iki ila üç kat daha yavaştır. Uygulamaya bakıldığında SeqLike[], bir oluşturucu oluşturulur, daha sonra dizi buna eklenir, ardından ekleme oluşturucu aracılığıyla yapılır, ardından oluşturucu oluşturulur. Diziler için iyi bir uygulama değil. On döngüden en hızlı zamana bakarak iki yöntemi karşılaştırarak hızlı bir kıyaslama yaptım. Bazı sınıfların 8 öğeli bir dizi örneğine tek öğeli bir ekin 10 milyon tekrarı yapmak , kullanılan basit bir yöntemle Foo3,1 saniye :+ve 1,7 saniye sürerappend()System.arraycopy();8 öğeli Long dizilerinde 10 milyon tek öğeli ekleme tekrarı :+yapmak, basit append()yöntemle 2,1 saniye ve 0,78 saniye sürer . Bunun kütüphanede özel bir uygulama ile düzeltilip düzeltilemeyeceğini merak ediyor Arraymusunuz?

Düzenle 2

Değeri ne olursa olsun, bir talepte bulundum: https://issues.scala-lang.org/browse/SI-5017


11
Neden kullanılmıyor ArrayBufferve +=yöntemi? Bu size amortize edilmiş O (1) eki verecektir.
Fred Foo

1
Ölçeklendirmede, System.arraycopy(...)yerineArray.copy(...)
paradigmatik

1
List vs Array'in avantajlarının ve dezavantajlarının farkındasınız, ancak 10 milyon eklentinin karşılaştırmalı sonuçlarına şaşırdınız mı?
kullanıcı bilinmiyor

Son eklemeden sonra bir diziye (ile ) ArrayBufferdönüştürülen bir kullanarak kıyaslamanızı tekrar çalıştırabilir misiniz ? toArray
paradigmatik

@paradigmatic: Kıyaslama tabii ki aynı diziye 10 milyon ekleme değil, 8 öğeli bir diziye tek öğeli bir ekin 10 milyon tekrarıydı. Soruyu buna göre güncelledim.
Gregor Scheidt

Yanıtlar:


204

Sen kullanabilirsiniz :+diziye ve eleman eklemek için +:bunu başa ekleyerek:

0 +: array :+ 4

üretmeli:

res3: Array[Int] = Array(0, 1, 2, 3, 4)

Diğer tüm uygulamalarla aynıdır Seq.


3
Scala sıralı diğer koleksiyonlar için de aynıdır , örneğin set ile çalışmaz (çünkü prepend ve append bir Set için hiçbir şey ifade etmez).
Nicolas

@Nicolas Herhangi bir sıra. Sıralı , sıralı anlamına gelir .
Daniel C. Sobral

@Daniel Evet, yorumu yazdığımda hafızamda küçük bir boşluk var ve bariz "sekans" kelimesini bulamadım
Nicolas

@tenshi tüm bu operatörler yeni bir dizi oluşturur mu? Evet, öyle (itibaren: + kod)Array.copy(repr, 0, result, 0, repr.length)
Timofey

60
val array2 = array :+ 4
//Array(1, 2, 3, 4)

Ayrıca "tersine" çalışır:

val array2 = 4 +: array
Array(4, 1, 2, 3)

Ayrıca "yerinde" bir sürüm de vardır:

var array = Array( 1, 2, 3 )
array +:= 4
//Array(4, 1, 2, 3)
array :+= 0
//Array(4, 1, 2, 3, 0)

11
Array koleksiyonunun neden ArrayBuffer gibi append () yöntemini kullanmadığını merak ediyorum. Kanımca, yeni bir operatör kullanmaktan daha fazla Koordinasyon ve birleştirme: + / +:
Djvu

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.