Array.Add vs + =

179

J'ai trouvé un comportement intéressant dans les tableaux PowerShell, à savoir si je déclare un tableau comme:

$array = @()

Et puis essayez d'y ajouter des éléments en utilisant la $array.Add("item")méthode, je reçois l'erreur suivante:

Exception appelant "Add" avec "1" argument (s): "La collection était de taille fixe."

Cependant, si j'ajoute des éléments en utilisant $array += "item", l'élément est accepté sans problème et la restriction "taille fixe" ne semble pas s'appliquer.

Pourquoi est-ce?

malgca
la source

Réponses:

254

Lorsque vous utilisez la $array.Add()méthode-, vous essayez d'ajouter l'élément dans le tableau existant. Un tableau est une collection de taille fixe, vous recevrez donc une erreur car il ne peut pas être étendu.

$array += $elementcrée un nouveau tableau avec les mêmes éléments que l'ancien + le nouvel élément, et ce nouveau tableau plus grand remplace l'ancien dans la $arrayvariable -variable

Vous pouvez utiliser l'opérateur + = pour ajouter un élément à un tableau. Lorsque vous l'utilisez, Windows PowerShell crée en fait un nouveau tableau avec les valeurs du tableau d'origine et la valeur ajoutée. Par exemple, pour ajouter un élément avec une valeur de 200 au tableau dans la variable $ a, tapez:

    $a += 200

Source: about_Arrays

+= est une opération coûteuse, donc lorsque vous devez ajouter de nombreux éléments, vous devez essayer de les ajouter en aussi peu d'opérations que possible, par exemple:

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

$arr.Count
5

Si ce n'est pas possible, envisagez d'utiliser une collection plus efficace comme Listou ArrayList(voir l'autre réponse).

Frode F.
la source
Merci :) Je pensais que c'était peut-être quelque chose comme ça, mais je pensais que ce serait inefficace avec de grands tableaux, donc l'équipe PowerShell faisait quelque chose de différent.
malgca
6
c'est tout à fait vrai, cela devient inefficace avec de grands tableaux, malheureusement pour contourner cela, vous devez utiliser un type différent: powershell.org/wp/2013/09/16/...
Nacht
3
Ça dépend. Si vous allez ajouter et supprimer de nombreux membres, alors oui, essayez Listou ArrayList. Ils seront beaucoup plus rapides. Personnellement, j'utilise +=et ma matrice 99% du temps parce que je crée généralement des scripts courts et jetables où les secondes supplémentaires n'ont pas d'importance. Pour les gros scripts avec beaucoup d'ajout / suppression où je veux optimiser et gagner du temps, j'utilise Listou ArrayList.
Frode F.
3
Comme les tableaux ont toujours une taille fixe, est-ce que quelqu'un sait pourquoi la Add()méthode existe?
JohnLBevan
4
Parce qu'il est hérité de IList. Essayez Get-Member -InputObject @()le montreraAdd Method int IList.Add(System.Object value)
Frode F.
113

Si vous voulez un tableau de taille dynamique, vous devez faire une liste. Non seulement vous obtiendrez la .Add()fonctionnalité, mais comme @ frode-f l'explique, les tableaux dynamiques sont plus efficaces en mémoire et une meilleure pratique de toute façon.

Et c'est tellement facile à utiliser.

Au lieu de votre déclaration de tableau, essayez ceci:

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

L'ajout d'éléments est simple.

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

Et si vous voulez vraiment un tableau lorsque vous avez terminé, il existe également une fonction pour cela.

$outItems.ToArray()
Sebastian Kaczmarek
la source
1
J'ai essayé ceci. Je le crée en utilisant New-Object System.Collections.Generic.List [string] mais si je fais .GetType, il me dit que c'est un tableau.
Preza8
1
Avez-vous essayé d'utiliser la Add()fonction? Je peux confirmer que si vous créez un Listobjet générique comme indiqué ci-dessus, vous avez une liste modifiable pour laquelle vous pouvez ajouter et supprimer des éléments en utilisant respectivement les méthodes Add()et Remove().
Bender the Greatest
1
@ Preza8: (New-Object System.Collections.Generic.List[string]).GetType().Namecède List`1pour moi, comme prévu; peut-être avez-vous appliqué +=à la variable contenant la liste (plutôt que d'appeler la .Add()méthode), auquel cas la valeur de la variable serait effectivement convertie en tableau ( System.Object[]).
mklement0
Raccourci:$a = new-object collections.generic.list[object]
Andrew
4

L'idiome le plus courant pour créer un tableau sans utiliser l'inefficace +=est quelque chose comme ceci, à partir de la sortie d'une boucle:

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