Array.Add vs + =

179

Encontré un comportamiento interesante en las matrices de PowerShell, a saber, si declaro una matriz como:

$array = @()

Y luego intente agregarle elementos usando $array.Add("item") método, recibo el siguiente error:

Excepción que llama a "Agregar" con "1" argumento (s): "La colección tenía un tamaño fijo".

Sin embargo, si agrego elementos usando $array += "item" , el elemento se acepta sin problemas y la restricción de "tamaño fijo" no parece aplicarse.

¿Por qué es esto?

malgca
fuente

Respuestas:

254

Cuando utiliza el $array.Add()método-, está intentando agregar el elemento a la matriz existente. Una matriz es una colección de tamaño fijo, por lo que recibirá un error porque no se puede extender.

$array += $elementcrea una nueva matriz con los mismos elementos que la anterior + el nuevo elemento, y esta nueva matriz más grande reemplaza a la anterior en la $arrayvariable

Puede usar el operador + = para agregar un elemento a una matriz. Cuando lo usa, Windows PowerShell realmente crea una nueva matriz con los valores de la matriz original y el valor agregado. Por ejemplo, para agregar un elemento con un valor de 200 a la matriz en la variable $ a, escriba:

    $a += 200

Fuente: about_Arrays

+= es una operación costosa, por lo que cuando necesite agregar muchos elementos, debe intentar agregarlos en la menor cantidad de operaciones posible, por ejemplo:

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

$arr.Count
5

Si eso no es posible, considere usar una colección más eficiente como Listo ArrayList(vea la otra respuesta).

Frode F.
fuente
Gracias :) Pensé que podría ser algo como esto, pero pensé que sería ineficiente con matrices grandes, por lo que el equipo de PowerShell estaba haciendo algo diferente.
malgca
66
eso es exactamente correcto, se vuelve ineficiente con matrices grandes, desafortunadamente para evitar esto, debe usar un tipo diferente: powershell.org/wp/2013/09/16/…
Nacht
3
Depende. Si va a agregar y eliminar muchos miembros, entonces sí, intente Listo ArrayList. Serán mucho más rápidos. Personalmente uso +=y organizo el 99% del tiempo porque generalmente creo scripts cortos de descarte donde los segundos adicionales no importan. Para secuencias de comandos grandes con una gran cantidad de agregar / quitar donde quiero optimizar y ahorrar tiempo utilizo Listo ArrayList.
Frode F.
3
Como las matrices son siempre de un tamaño fijo, ¿alguien sabe por qué Add()existe el método?
JohnLBevan
44
Porque se hereda de IList. Intenta Get-Member -InputObject @()mostrar estoAdd Method int IList.Add(System.Object value)
Frode F.
113

Si desea una matriz de tamaño dinámico, debe hacer una lista. No solo obtendrá la .Add()funcionalidad, sino que, como explica @ frode-f, las matrices dinámicas son más eficientes en memoria y, de todos modos, son una mejor práctica.

Y es muy fácil de usar.

En lugar de su declaración de matriz, intente esto:

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

Agregar elementos es simple.

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

Y si realmente quieres una matriz cuando hayas terminado, también hay una función para eso.

$outItems.ToArray()
Sebastian Kaczmarek
fuente
1
He intentado esto Lo creo usando New-Object System.Collections.Generic.List [string] pero luego, si lo hago .GetType, me dice que es una matriz.
Preza8
1
¿Has intentado usar la Add()función? Puedo confirmar que si crea un Listobjeto genérico como se indicó anteriormente, tiene una lista mutable para la que puede agregar y eliminar elementos utilizando los métodos Add()y Remove()respectivamente.
Bender the Greatest
1
@ Preza8: (New-Object System.Collections.Generic.List[string]).GetType().Namerinde List`1para mí, como se esperaba; quizás aplicó +=a la variable que contiene la lista (en lugar de llamar al .Add()método), en cuyo caso el valor de la variable se convertiría en una matriz ( System.Object[]).
mklement0
Atajo:$a = new-object collections.generic.list[object]
Andrew
4

El idioma más común para crear una matriz sin usar el ineficiente +=es algo así, a partir de la salida de un bucle:

$array = foreach($i in 1..10) { 
  $i
}
$array
js2010
fuente