Scala: qual é a melhor maneira de anexar um elemento a um Array?


111

Diga que tenho um Array[Int]gosto

val array = Array( 1, 2, 3 )

Agora, gostaria de acrescentar um elemento à matriz, digamos o valor 4, como no exemplo a seguir:

val array2 = array + 4     // will not compile

Claro que posso usar System.arraycopy()e fazer isso sozinho, mas deve haver uma função de biblioteca Scala para isso, que simplesmente não consegui encontrar. Obrigado por quaisquer dicas!

Notas:

  1. Estou ciente de que posso acrescentar outro Array de elementos, como na linha a seguir, mas isso parece muito genérico:

    val array2b = array ++ Array( 4 )     // this works
  2. Estou ciente das vantagens e desvantagens de List vs Array e aqui estou, por vários motivos, especificamente interessado em estender um Array.

Editar 1

Obrigado pelas respostas apontando para o :+método do operador. Isso é o que eu estava procurando. Infelizmente, é um pouco mais lento do que a implementação de um método append () personalizado usando arraycopy- cerca de duas a três vezes mais lento. Observando a implementação em SeqLike[], um construtor é criado, a matriz é incluída nele, a anexação é feita por meio do construtor e, em seguida, o construtor é renderizado. Não é uma boa implementação para arrays. Fiz um benchmark rápido comparando os dois métodos, observando o tempo mais rápido entre dez ciclos. Fazer 10 milhões de repetições de um único item anexado a uma instância de matriz de 8 elementos de alguma classe Fooleva 3,1 segundos :+e 1,7 segundos com um append()método simples que usaSystem.arraycopy();fazer 10 milhões de repetições de acréscimo de item único em arrays de 8 elementos de Long leva 2,1 segundos :+e 0,78 segundos com o append()método simples . Gostaria de saber se isso não poderia ser corrigido na biblioteca com uma implementação personalizada para Array?

Editar 2

Para valer a pena, preenchi um tíquete: https://issues.scala-lang.org/browse/SI-5017


11
Por que não usar ArrayBuffere seu +=método? Isso lhe dará o anexo O (1) amortizado.
Fred Foo

1
Em scala, System.arraycopy(...)é substituído porArray.copy(...)
paradigmático

1
Você está ciente das vantagens e desvantagens de List vs Array, mas ficou surpreso com os resultados de benchmark de 10 milhões de anexos?
usuário desconhecido

Você pode executar novamente seu benchmark usando um ArrayBufferque é convertido após o último acréscimo em um array (com toArray)?
paradigmático de

@paradigmatic: O benchmark, é claro, não foi 10 milhões de anexos no mesmo array, mas 10 milhões de repetições de um único item em um array de 8 elementos. Eu atualizei a pergunta de acordo.
Gregor Scheidt,

Respostas:


204

Você pode usar :+para acrescentar um elemento à matriz e +:para acrescentá -lo:

0 +: array :+ 4

deve produzir:

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

É o mesmo que qualquer outra implementação de Seq.


3
É o mesmo para qualquer outra coleção ordenada de scala , não funciona com set, por exemplo (já que prefixar e acrescentar não significa nada para um Set).
Nicolas

@Nicolas Qualquer sequência. Ordenado implica ordenado .
Daniel C. Sobral,

@Daniel Sim, acabei de ter um pequeno buraco na memória quando escrevi o comentário e não encontrei a palavra óbvia "sequência"
Nicolas

@tenshi, todos esses operadores criariam um novo array? Sim, é (de: + código)Array.copy(repr, 0, result, 0, repr.length)
Timofey,

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

Funciona também "invertido":

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

Também existe uma versão "no local":

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

11
Eu só me pergunto por que a coleção Array não usa o método append (), assim como o ArrayBuffer. Na minha opinião, é mais Coordenação e unificação do que usar um novo operador: + / +:
Djvu

8

O mais fácil pode ser:

Array(1, 2, 3) :+ 4

Na verdade, Array pode ser transformado implcitamente em um WrappedArray


Nesse caso, seria a conversão de maior prioridade para ArrayOps
Didier Dupont
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.