Scala: quelle est la meilleure façon d'ajouter un élément à un tableau?

111

Dis que j'ai un Array[Int]comme

val array = Array( 1, 2, 3 )

Maintenant, je voudrais ajouter un élément au tableau, disons la valeur 4, comme dans l'exemple suivant:

val array2 = array + 4     // will not compile

Je peux bien sûr utiliser System.arraycopy()et faire cela par moi-même, mais il doit y avoir une fonction de bibliothèque Scala pour cela, que je n'ai tout simplement pas pu trouver. Merci pour tous les conseils!

Remarques:

  1. Je suis conscient que je peux ajouter un autre tableau d'éléments, comme dans la ligne suivante, mais cela semble trop rond:

    val array2b = array ++ Array( 4 )     // this works
  2. Je suis conscient des avantages et des inconvénients de List vs Array et me voici pour diverses raisons spécifiquement intéressé par l'extension d'un Array.

Modifier 1

Merci pour les réponses pointant vers la :+méthode opérateur. C'est ce que je cherchais. Malheureusement, il est plutôt plus lent qu'une implémentation de méthode append () personnalisée en utilisant arraycopy- environ deux à trois fois plus lent. En regardant l'implémentation dans SeqLike[], un générateur est créé, puis le tableau y est ajouté, puis l'ajout se fait via le générateur, puis le générateur est rendu. Pas une bonne implémentation pour les tableaux. J'ai fait une comparaison rapide des deux méthodes, en regardant le temps le plus rapide sur dix cycles. Faire 10 millions de répétitions d'un seul élément ajouté à une instance de tableau à 8 éléments d'une classe Fooprend 3,1 s avec :+et 1,7 s avec une append()méthode simple qui utiliseSystem.arraycopy();faire 10 millions de répétitions d'ajout d'un seul élément sur des tableaux de 8 éléments de Long prend 2,1 s avec :+et 0,78 s avec la append()méthode simple . Je me demande si cela ne peut pas être corrigé dans la bibliothèque avec une implémentation personnalisée pour Array?

Modifier 2

Pour ce que ça vaut, j'ai déposé un ticket: https://issues.scala-lang.org/browse/SI-5017

Gregor Scheidt
la source
11
Pourquoi ne pas utiliser ArrayBufferet sa +=méthode? Cela vous donnera un ajout O (1) amorti.
Fred Foo
1
Dans scala, System.arraycopy(...)est remplacé parArray.copy(...)
paradigmatic
1
Vous êtes conscient des avantages et des inconvénients de List vs Array, mais êtes surpris des résultats de référence de 10 millions d'ajouts?
utilisateur inconnu du
Pouvez-vous exécuter à nouveau votre benchmark en utilisant un ArrayBufferqui est converti après le dernier ajout à un tableau (avec toArray)?
paradigmatic
@paradigmatic: La référence n'était bien sûr pas 10 millions d'ajouts au même tableau, mais 10 millions de répétitions d'un seul élément ajouté à un tableau de 8 éléments. J'ai mis à jour la question en conséquence.
Gregor Scheidt

Réponses:

204

Vous pouvez utiliser :+pour ajouter un élément au tableau et +:le préfixer:

0 +: array :+ 4

devrait produire:

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

C'est la même chose que pour toute autre implémentation de Seq.

tenshi
la source
3
C'est la même chose pour toute autre collection ordonnée par scala , cela ne fonctionne pas avec set par exemple (comme préfixer et ajouter ne signifie rien pour un ensemble).
Nicolas
@Nicolas N'importe quelle séquence. Ordonné implique trié .
Daniel C.Sobral
@Daniel Oui, j'ai juste un petit trou de mémoire quand j'ai écrit le commentaire et je n'ai pas trouvé le mot évident "séquence"
Nicolas
@tenshi tous ces opérateurs créeraient-ils un nouveau tableau? Oui, c'est le cas (à partir de: + code)Array.copy(repr, 0, result, 0, repr.length)
Timofey
59
val array2 = array :+ 4
//Array(1, 2, 3, 4)

Fonctionne également "inversé":

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

Il existe également une version "sur place":

var array = Array( 1, 2, 3 )
array +:= 4
//Array(4, 1, 2, 3)
array :+= 0
//Array(4, 1, 2, 3, 0)
Landei
la source
11
Je me demande simplement pourquoi la collection Array n'utilise pas la méthode append (), tout comme ArrayBuffer. A mon avis, il s'agit plus de Coordination et d'unification que d'utiliser un nouvel opérateur: + / +:
Djvu
8

Le plus simple pourrait être:

Array(1, 2, 3) :+ 4

En fait, Array peut être implicitement transformé en un WrappedArray

Nicolas
la source
Dans ce cas, ce serait la conversion la plus prioritaire vers ArrayOps
Didier Dupont