Array.Addと+ =


179

PowerShell配列でいくつかの興味深い動作を見つけました。つまり、配列を次のように宣言した場合です。

$array = @()

$array.Add("item")メソッドを使用してアイテムを追加しようとすると、次のエラーが表示されます。

「1」の引数で「追加」を呼び出す例外:「コレクションは固定サイズでした。」

ただし、を使用してアイテムを追加する$array += "item"と、アイテムは問題なく受け入れられ、「固定サイズ」の制限が適用されないようです。

どうしてこれなの?

回答:


254

$array.Add()-メソッドを使用すると、要素を既存の配列に追加しようとしています。配列は固定サイズのコレクションであるため、拡張できないためエラーが発生します。

$array += $element古いものと同じ要素と新しい項目を持つ新しい配列を作成し、この新しい大きな配列が$array-variableの古い配列を置き換えます

+ =演算子を使用して、要素を配列に追加できます。これを使用すると、Windows PowerShellは実際には、元の配列の値と追加された値で新しい配列を作成します。たとえば、$ a変​​数の配列に値が200の要素を追加するには、次のように入力します。

    $a += 200

出典:about_Arrays

+= は高価な操作であるため、多くのアイテムを追加する必要がある場合は、できるだけ少ない操作で追加するようにしてください。例:

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

$arr.Count
5

それが不可能な場合は、Listorなどのより効率的なコレクションの使用を検討してArrayListください(他の回答を参照)。


ありがとう:)これはこのようなものかもしれませんが、大きな配列では非効率的だと思ったので、Powershellチームは別のことをしていました。
malgca 2013年

6
:まさにそうです、それは残念ながらあなたが別のタイプを使用する必要があり、この周りを取得するために、大規模な配列と非効率的になるpowershell.org/wp/2013/09/16/...
NACHT

3
場合によります。多数のメンバーを追加および削除する場合は、はい、Listまたはを試してくださいArrayList。彼らははるかに速くなります。私は個人的に使用し+=、99%の時間を配列しています。通常、余分な秒数が問題にならない短い使い捨てスクリプトを作成するためです。最適化して時間を節約したい追加/削除の多い大きなスクリプトの場合、Listまたはを使用しますArrayList
Frode F.

3
配列は常に固定サイズであるため、Add()メソッドが存在する理由を誰かが知っていますか?
JohnLBevan 2017年

4
から継承されているためIListです。トライはGet-Member -InputObject @()これが表示されますAdd Method int IList.Add(System.Object value)
フローデ・F.

113

動的なサイズの配列が必要な場合は、リストを作成する必要があります。.Add()機能が得られるだけでなく、@ frode-fで説明されているように、動的配列の方がメモリ効率が高く、とにかく優れた方法です。

そして、それはとても使いやすいです。

配列宣言の代わりに、これを試してください:

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

アイテムの追加は簡単です。

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

そして、完了時に本当に配列が必要な場合は、そのための関数もあります。

$outItems.ToArray()

1
私はこれを試しました。New-Object System.Collections.Generic.List [string]を使用して作成していますが、.GetTypeを実行すると、配列であることがわかります。
Preza8 2017年

1
このAdd()機能を使ってみましたか?List上記のように汎用オブジェクトを作成すると、Add()およびRemove()メソッドをそれぞれ使用して項目を追加および削除できる変更可能なリストがあることを確認できます。
Bender the Greatest

1
@ Preza8:予想通り、私にとっての(New-Object System.Collections.Generic.List[string]).GetType().Name利回りList`1+=.Add()メソッドを呼び出すのではなく)リストを含む変数に適用した可能性があります。その場合、変数の値は実際に配列(System.Object[])に変換されます。
mklement0 2017

ショートカット:$a = new-object collections.generic.list[object]
Andrew

4

非効率を使用せずに配列を作成するための最も一般的なイディオム+=は、ループの出力から次のようなものです:

$array = foreach($i in 1..10) { 
  $i
}
$array
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.