Array.Add vs + =

178

Ich habe in PowerShell-Arrays ein interessantes Verhalten festgestellt, nämlich wenn ich ein Array wie folgt deklariere:

$array = @()

Und dann versuchen Sie, Elemente mit der $array.Add("item")Methode hinzuzufügen. Ich erhalte die folgende Fehlermeldung:

Ausnahme beim Aufrufen von "Hinzufügen" mit "1" Argument (en): "Sammlung hatte eine feste Größe."

Wenn ich jedoch Elemente mit anhänge $array += "item", wird das Element problemlos akzeptiert und die Einschränkung "feste Größe" scheint nicht zu gelten.

Warum ist das?

malgca
quelle

Antworten:

253

Wenn Sie die $array.Add()Methode -method verwenden, versuchen Sie, das Element dem vorhandenen Array hinzuzufügen. Ein Array ist eine Sammlung fester Größe, daher wird eine Fehlermeldung angezeigt, da es nicht erweitert werden kann.

$array += $elementErstellt ein neues Array mit denselben Elementen wie das alte + das neue Element, und dieses neue größere Array ersetzt das alte in der $arrayVariablen

Mit dem Operator + = können Sie einem Array ein Element hinzufügen. Wenn Sie es verwenden, erstellt Windows PowerShell tatsächlich ein neues Array mit den Werten des ursprünglichen Arrays und dem Mehrwert. Geben Sie beispielsweise Folgendes ein, um dem Array in der Variablen $ a ein Element mit dem Wert 200 hinzuzufügen.

    $a += 200

Quelle: about_Arrays

+= ist eine teure Operation. Wenn Sie also viele Elemente hinzufügen müssen, sollten Sie versuchen, sie in so wenigen Operationen wie möglich hinzuzufügen, z.

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

$arr.Count
5

Wenn dies nicht möglich ist, sollten Sie eine effizientere Sammlung wie Listoder verwenden ArrayList(siehe die andere Antwort).

Frode F.
quelle
Danke :) Ich dachte, es könnte so etwas sein, dachte aber, es wäre bei großen Arrays ineffizient, also machte das Powershell-Team etwas anderes.
Malgca
6
Das ist genau richtig, es wird bei großen Arrays ineffizient. Um dies zu umgehen
Nacht
3
Es hängt davon ab, ob. Wenn Sie viele Mitglieder hinzufügen und entfernen möchten, versuchen Sie es mit Listoder ArrayList. Sie werden viel schneller sein. Ich persönlich verwende +=und arrangiere 99% der Zeit, weil ich normalerweise kurze Wegwerf-Skripte erstelle, bei denen die zusätzlichen Sekunden keine Rolle spielen. Für große Skripte mit viel Hinzufügen / Entfernen, bei denen ich optimieren oder Zeit sparen möchte, verwende ich Listoder ArrayList.
Frode F.
3
Weiß jemand, warum die Add()Methode existiert, da Arrays immer eine feste Größe haben ?
JohnLBevan
4
Weil es von geerbt ist IList. Versuch Get-Member -InputObject @()wird dies zeigenAdd Method int IList.Add(System.Object value)
Frode F.
113

Wenn Sie ein Array mit dynamischer Größe wünschen, sollten Sie eine Liste erstellen. Sie erhalten nicht nur die .Add()Funktionalität, sondern, wie @ frode-f erklärt, sind dynamische Arrays speichereffizienter und ohnehin eine bessere Vorgehensweise.

Und es ist so einfach zu bedienen.

Versuchen Sie anstelle Ihrer Array-Deklaration Folgendes:

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

Das Hinzufügen von Elementen ist einfach.

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

Und wenn Sie wirklich ein Array wollen, wenn Sie fertig sind, gibt es auch eine Funktion dafür.

$outItems.ToArray()
Sebastian Kaczmarek
quelle
1
Ich habe es versucht. Ich erstelle es mit New-Object System.Collections.Generic.List [string], aber wenn ich .GetType mache, wird mir mitgeteilt, dass es sich um ein Array handelt.
Preza8
1
Haben Sie versucht, die Add()Funktion zu verwenden? Ich kann bestätigen, dass Sie, wenn Sie ein generisches ListObjekt wie oben angegeben erstellen , eine veränderbare Liste haben, für die Sie Elemente mit den Methoden Add()und hinzufügen bzw. entfernen können Remove().
Bender der Größte
1
@ Preza8: (New-Object System.Collections.Generic.List[string]).GetType().NameErträge List`1für mich, wie erwartet; Vielleicht haben Sie +=auf die Variable angewendet , die die Liste enthält (anstatt die .Add()Methode aufzurufen ). In diesem Fall würde der Variablenwert tatsächlich in ein Array konvertiert ( System.Object[]).
mklement0
Abkürzung:$a = new-object collections.generic.list[object]
Andrew
4

Die gebräuchlichste Redewendung zum Erstellen eines Arrays ohne Verwendung des Ineffizienten +=ist etwa die folgende aus der Ausgabe einer Schleife:

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