Array.Add vs + =


179

Ho trovato un comportamento interessante negli array PowerShell, vale a dire se dichiaro un array come:

$array = @()

E quindi provare ad aggiungere elementi ad esso utilizzando il $array.Add("item")metodo, ricevo il seguente errore:

Eccezione che chiama "Aggiungi" con "1" argomento: "La raccolta era di dimensioni fisse".

Tuttavia, se allego elementi utilizzando $array += "item", l'oggetto viene accettato senza problemi e la restrizione "dimensioni fisse" non sembra essere applicabile.

Perchè è questo?

Risposte:


254

Quando si utilizza il $array.Add()metodo, si sta tentando di aggiungere l'elemento alla matrice esistente. Un array è una raccolta di dimensioni fisse, quindi riceverai un errore perché non può essere esteso.

$array += $elementcrea un nuovo array con gli stessi elementi di quello vecchio + il nuovo oggetto, e questo nuovo array più grande sostituisce quello vecchio nella $arrayvariabile

È possibile utilizzare l'operatore + = per aggiungere un elemento a un array. Quando lo si utilizza, Windows PowerShell crea effettivamente un nuovo array con i valori dell'array originale e il valore aggiunto. Ad esempio, per aggiungere un elemento con un valore di 200 all'array nella variabile $ a, digitare:

    $a += 200

Fonte: about_Arrays

+= è un'operazione costosa, quindi quando devi aggiungere molti elementi dovresti provare ad aggiungerli nel minor numero di operazioni possibile, ad esempio:

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

$arr.Count
5

Se ciò non è possibile, considera l'utilizzo di una raccolta più efficiente come Listo ArrayList(vedi l'altra risposta).


Grazie :) Ho pensato che potesse essere qualcosa del genere, ma ho pensato che sarebbe stato inefficiente con array di grandi dimensioni, quindi il team PowerShell stava facendo qualcosa di diverso.
Malgca,

6
esatto, diventa inefficiente con array di grandi dimensioni, sfortunatamente per aggirare il problema devi usare un tipo diverso: powershell.org/wp/2013/09/16/…
Nacht,

3
Dipende. Se hai intenzione di aggiungere e rimuovere molti membri, sì, prova Listo ArrayList. Saranno molto più veloci. Personalmente utilizzo +=e array il 99% delle volte perché di solito creo brevi script usa e getta in cui i secondi extra non contano. Per gli script di grandi dimensioni con un sacco di aggiungere / rimuovere dove voglio ottimizzare e risparmiare tempo che uso Listo ArrayList.
Frode F.,

3
Poiché le matrici hanno sempre dimensioni fisse, qualcuno sa perché Add()esiste il metodo?
JohnLBevan,

4
Perché è ereditato da IList. Try Get-Member -InputObject @()mostrerà questoAdd Method int IList.Add(System.Object value)
Frode F.

113

Se si desidera un array di dimensioni dinamiche, è necessario creare un elenco. Non solo otterrai la .Add()funzionalità, ma come spiega @ frode-f, gli array dinamici sono più efficienti in termini di memoria e comunque una pratica migliore.

Ed è così facile da usare.

Invece della tua dichiarazione di array, prova questo:

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

L'aggiunta di elementi è semplice.

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

E se vuoi davvero un array quando hai finito, c'è anche una funzione per quello.

$outItems.ToArray()

1
Ci ho provato Lo creo usando New-Object System.Collections.Generic.List [stringa] ma poi se lo faccio .GetType, mi dice che è un array.
Preza8,

1
Hai provato a usare la Add()funzione? Posso confermare, se si crea un Listoggetto generico come indicato sopra, si dispone di un elenco modificabile per il quale è possibile aggiungere e rimuovere elementi utilizzando rispettivamente i metodi Add()e Remove().
Bender the Greatest,

1
@ Preza8: (New-Object System.Collections.Generic.List[string]).GetType().Namerese List`1per me, come previsto; forse hai applicato +=la variabile contenente l'elenco (anziché chiamare il .Add()metodo), nel qual caso il valore della variabile verrebbe effettivamente convertito in un array ( System.Object[]).
mklement0,

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

4

Il linguaggio più comune per creare un array senza usare l'inefficiente +=è qualcosa di simile, dall'output di un loop:

$array = foreach($i in 1..10) { 
  $i
}
$array
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.