Scala: jaki jest najlepszy sposób na dołączenie elementu do tablicy?


111

Powiedz, że Array[Int]lubię

val array = Array( 1, 2, 3 )

Teraz chciałbym dołączyć element do tablicy, powiedzmy wartość 4, jak w poniższym przykładzie:

val array2 = array + 4     // will not compile

Mogę oczywiście używać System.arraycopy()i robić to samodzielnie, ale musi być do tego funkcja biblioteki Scala, której po prostu nie mogłem znaleźć. Dzięki za wskazówki!

Uwagi:

  1. Zdaję sobie sprawę, że mogę dołączyć kolejną tablicę elementów, jak w poniższym wierszu, ale wydaje się to zbyt okrągłe:

    val array2b = array ++ Array( 4 )     // this works
  2. Zdaję sobie sprawę z zalet i wad List vs Array i tutaj jestem z różnych powodów szczególnie zainteresowany rozszerzeniem Array.

Edytuj 1

Dzięki za odpowiedzi wskazujące na :+metodę operatorską. To jest to, czego szukałem. Niestety jest to raczej wolniejsze niż implementacja niestandardowej metody append () arraycopy- około dwa do trzech razy wolniejsza. Patrząc na implementację w programie SeqLike[], tworzony jest konstruktor, następnie tablica jest do niej dodawana, a następnie dodawane jest za pośrednictwem konstruktora, a następnie renderowany jest konstruktor. Niezbyt dobra implementacja dla tablic. Zrobiłem szybki test porównawczy, porównując dwie metody, patrząc na najszybszy czas z dziesięciu cykli. Wykonanie 10 milionów powtórzeń pojedynczego elementu dołączanego do 8-elementowej instancji tablicy pewnej klasy Foozajmuje 3,1 sekundy :+zi 1,7 sekundy przy użyciu prostej append()metodySystem.arraycopy();wykonanie 10 milionów powtórzeń dopisywania pojedynczych pozycji na 8-elementowych tablicach Long zajmuje 2,1 sekundy z :+prostą append()metodą i 0,78 sekundy . Zastanawiasz się, czy nie można tego naprawić w bibliotece za pomocą niestandardowej implementacji Array?

Edytuj 2

Za to, co jest warte, złożyłem bilet: https://issues.scala-lang.org/browse/SI-5017


11
Dlaczego nie użyć ArrayBufferi jego +=metody? To da ci zamortyzowany O (1) dodatek.
— Fred Foo

1
W scali System.arraycopy(...)zostaje zastąpiony przezArray.copy(...)
— paradygmatyczny

1
Czy zdajesz sobie sprawę z zalet i wad funkcji List vs Array, ale jesteś zaskoczony wynikami testów porównawczych 10 milionów dołączeń?
— użytkownik nieznany

Czy możesz ponownie uruchomić test porównawczy, używając elementu, ArrayBufferktóry jest konwertowany po ostatnim dołączeniu do tablicy (z toArray)?
— paradygmatyczny

@paradigmatic: Wzorem oczywiście nie było 10 milionów dodań do tej samej tablicy, ale 10 milionów powtórzeń dołączenia pojedynczego elementu do 8-elementowej tablicy. Odpowiednio zaktualizowałem pytanie.
— Gregor Scheidt

Odpowiedzi:


204

Możesz użyć, :+aby dołączyć element do tablicy i +:poprzedzić go:

0 +: array :+ 4

powinien produkować:

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

Działa tak samo, jak w przypadku każdej innej implementacji Seq.


3
Tak samo jest z każdą inną uporządkowaną kolekcją scala , nie działa na przykład z zestawem (ponieważ dołączanie i dołączanie nie ma znaczenia dla zestawu).
— Nicolas,

@Nicolas Dowolna sekwencja. Uporządkowane implikacje posortowane .
— Daniel C. Sobral,

@Daniel Tak, po napisaniu komentarza mam małą dziurkę w pamięci i nie znalazłem oczywistego słowa „sekwencja”
— Nicolas

@tenshi czy wszystkie te operatory utworzyłyby nową tablicę? Tak, działa (od: + kod)Array.copy(repr, 0, result, 0, repr.length)
— Timofey

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

Działa również „odwrócony”:

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

Dostępna jest również wersja „lokalna”:

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

11
Zastanawiam się tylko, dlaczego kolekcja Array nie używa metody append (), tak jak ArrayBuffer. Moim zdaniem to bardziej Koordynacja i ujednolicenie niż użycie nowego operatora: + / +:
— Djvu

8

Najłatwiej byłoby:

Array(1, 2, 3) :+ 4

W rzeczywistości Array można implcitly przekształcić w plik WrappedArray


W takim przypadku byłaby to konwersja o wyższym priorytecie do ArrayOps
— Didier Dupont
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.