Array.Add vs + =


179

Encontrei algum comportamento interessante nas matrizes do PowerShell, a saber, se eu declarar uma matriz como:

$array = @()

E, em seguida, tente adicionar itens a ele usando o $array.Add("item")método, recebo o seguinte erro:

Exceção que chama "Adicionar" com argumento (s) "1": "A coleção era de tamanho fixo".

No entanto, se eu anexar itens usando $array += "item", o item será aceito sem problemas e a restrição "tamanho fixo" parece não se aplicar.

Por que é isso?

Respostas:


254

Ao usar o $array.Add()método, você está tentando adicionar o elemento à matriz existente. Uma matriz é uma coleção de tamanho fixo; portanto, você receberá um erro porque não pode ser estendido.

$array += $elementcria uma nova matriz com os mesmos elementos que a antiga + o novo item, e essa nova matriz maior substitui a antiga na $arrayvariável -variable

Você pode usar o operador + = para adicionar um elemento a uma matriz. Quando você o usa, o Windows PowerShell realmente cria uma nova matriz com os valores da matriz original e o valor agregado. Por exemplo, para adicionar um elemento com um valor de 200 à matriz na variável $ a, digite:

    $a += 200

Fonte: about_Arrays

+= é uma operação cara, portanto, quando você precisar adicionar muitos itens, tente adicioná-los no menor número de operações possível, por exemplo:

$arr = 1..3    #Array
$arr += (4..5) #Combine with another array in a single write-operation

$arr.Count
5

Se isso não for possível, considere usar uma coleção mais eficiente como Listou ArrayList(consulte a outra resposta).


Obrigado :) Achei que poderia ser algo assim, mas achei que seria ineficiente com matrizes grandes, então a equipe do PowerShell estava fazendo algo diferente.
malgca

6
isso é exatamente correto, torna-se ineficiente com matrizes grandes. Infelizmente, para contornar isso, você precisa usar um tipo diferente: powershell.org/wp/2013/09/16/…
Nacht

3
Depende. Se você deseja adicionar e remover muitos membros, sim, tente Listou ArrayList. Eles serão muito mais rápidos. Pessoalmente, uso +=e organizo 99% do tempo, porque geralmente crio pequenos scripts descartáveis, onde os segundos extras não importam. Para scripts grandes com muitas opções de adição / remoção, onde eu quero otimizar e economizar tempo que uso Listou ArrayList.
Frode F.

3
Como as matrizes são sempre de tamanho fixo, alguém sabe por que o Add()método existe?
JohnLBevan

4
Porque é herdado de IList. Tente Get-Member -InputObject @()irá mostrar issoAdd Method int IList.Add(System.Object value)
Frode F.

113

Se você deseja uma matriz de tamanho dinâmico, faça uma lista. Você não apenas obterá a .Add()funcionalidade, mas como o @ frode-f explica, matrizes dinâmicas são mais eficientes em termos de memória e, de qualquer maneira, são uma prática melhor.

E é tão fácil de usar.

Em vez da sua declaração de matriz, tente o seguinte:

$outItems = New-Object System.Collections.Generic.List[System.Object]

Adicionar itens é simples.

$outItems.Add(1)
$outItems.Add("hi")

E se você realmente deseja uma matriz quando terminar, também há uma função para isso.

$outItems.ToArray()

1
Eu tentei isso. Eu o crio usando o New-Object System.Collections.Generic.List [string], mas se o faço .GetType, ele diz que é uma matriz.
Preza8

1
Você já tentou usar a Add()função? Posso confirmar que, se você criar um Listobjeto genérico conforme mencionado acima, terá uma lista mutável para a qual poderá adicionar e remover itens usando os métodos Add()e Remove(), respectivamente.
Bender the Greatest

1
@ Preza8: (New-Object System.Collections.Generic.List[string]).GetType().Namerende List`1para mim, como esperado; talvez você tenha se aplicado +=à variável que contém a lista (em vez de chamar o .Add()método); nesse caso, o valor da variável seria realmente convertido em uma matriz ( System.Object[]).
mklement0

Atalho:$a = new-object collections.generic.list[object]
Andrew

4

O idioma mais comum para criar uma matriz sem usar o ineficiente +=é algo assim, a partir da saída de um loop:

$array = foreach($i in 1..10) { 
  $i
}
$array
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.