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?

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).


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()

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.