9. 配列

9.1 はじめに

PowerShell では、1 つ以上の次元の配列がサポートされ、各次元には 0 個以上の 要素 が含まれています。 次元内では、各要素に 0 から始まる整数の番号が昇順で付けられます。 配列添字演算子 [] (§7.1.4) を使用して、個々の要素にアクセスできます。 配列の次元数は、その ランク と呼ばれます。

要素には、配列型を含む任意の型の値を含めることができます。 その値がいずれかの配列型である 1 つ以上の要素を持つ配列は、ジャグ配列 と呼ばれます。 多次元配列 には複数の次元があります。その場合、次元の各行の要素の数は同じです。 ジャグ配列の要素には多次元配列が含まれる場合があり、その逆もあります。

多次元配列は、行優先の順序で格納されます。 配列内の要素の数は、その配列の 長さ と呼ばれ、配列の作成時に固定されます。 そのため、長さ N の 1 次元配列 A の要素には、式 A[0], A[1], ..., A[N-1] を使用してアクセスできます (つまり、添字が付けられます)。 各行に N 列が含まれ、M 行を含む 2 次元配列 B の要素には式 B[0,0], B[0,1], ..., B[0,N-1], B[1,0], B[1,1], ..., B[1,N-1], ..., B[M-1,0], B[M-1,1], ..., B[M-1,N-1] を使用してアクセスできます。 3 つ以上の次元を持つ配列の場合も同じになります。

既定では、配列は ポリモーフィック です。つまり、すべての要素が同じ型である必要はありません。 たとえば、次のように入力します。

$items = 10,"blue",12.54e3,16.30D # 1-D array of length 4
$items[1] = -2.345
$items[2] = "green"

$a = New-Object 'object[,]' 2,2 # 2-D array of length 4
$a[0,0] = 10
$a[0,1] = $false
$a[1,0] = "red"
$a[1,1] = $null

1 次元配列の型が type[]、2 次元配列の型が type[,]、3 次元配列の型が type[,,] です。ここでの とは、制約のない型の配列、または制約付き配列 (§9.4) の制約付きの型のオブジェクトです。

すべての配列型は、Array 型 (§4.3.2) 型から派生します。

9.2 配列作成

配列は、配列作成式 を使用して作成されます。これには、単項コンマ演算子 (§7.2.1)、array-expression (§7.1.7)、二項コンマ演算子 (§7.3)、範囲演算子 (§7.4)、または New-Object コマンドレットの形式が含まれます。

配列の作成と使用の例を次に示します。

$values = 10, 20, 30
for ($i = 0; $i -lt $values.Length; ++$i) {
    "`$values[$i] = $($values[$i])"
}

$x = , 10                         # x refers to an array of length 1
$x = @(10)                        # x refers to an array of length 1
$x = @()                          # x refers to an array of length 0

$a = New-Object 'object[,]' 2, 2  # create a 2x2 array of anything
$a[0, 0] = 10                     # set to an int value
$a[0, 1] = $false                 # set to a boolean value
$a[1, 0] = "red"                  # set to a string value
$a[1, 1] = 10.50D                 # set to a decimal value
foreach ($e in $a) {              # enumerate over the whole array
    $e
}

次がパイプラインに書き込まれます。

$values[0] = 10
$values[1] = 20
$values[2] = 30

10
False
red
10.50

明示的に初期化されていない要素の既定の初期値は、その要素の型の既定値 ($false、0、または $null) です。

9.3 配列連結

任意の型と長さの配列は、++= の演算子を使用して連結できます。その両方で、新しい制約なしの 1 次元配列が作成されます。 既存の配列は変更されません。 詳細については §7.7.3 を、制約付きの型の配列への追加の説明は §9.4 を参照してください。

9.4 要素型の制約

配列作成式の前に配列型キャストを付けて、型制約がある 1 次元配列を作成できます。 たとえば、次のように入力します。

$a = [int[]](1,2,3,4)   # constrained to int
$a[1] = "abc"           # implementation-defined behavior
$a += 1.23              # new array is unconstrained

多次元配列を作成するための構文では、型を指定する必要があります。その型は、その配列の制約型になります。 ただし、object[] 型を指定しても、すべての型の値がその型の配列の要素に割り当てられるため、実際には制約がありません。

2 つの配列を連結する (§7.7.3) と、両方の配列が同じ型の制約を受けている場合でも、常に制約のない新しい配列が作成されます。 たとえば、次のように入力します。

$a = [int[]](1,2,3)    # constrained to int
$b = [int[]](10,20)    # constrained to int
$c = $a + $b           # constraint not preserved
$c = [int[]]($a + $b)  # result explicitly constrained to int

9.5 参照型としての配列

配列型は参照型であり、配列を指定する変数を、任意のランク、長さ、および要素型の任意の配列を参照するようにできます。 たとえば、次のように入力します。

$a = 10,20                     # $a refers to an array of length 2
$a = 10,20,30                  # $a refers to a different array, of length 3
$a = "red",10.6                # $a refers to a different array, of length 2
$a = New-Object 'int[,]' 2,3   # $a refers to an array of rank 2

配列の代入には、シャロウ コピーが含まれます。つまり、割り当てられた変数は同じ配列を参照します。配列のコピーは作成されません。 たとえば、次のように入力します。

$a = 10,20,30
">$a<"
$b = $a         # make $b refer to the same array as $a
">$b<"

$a[0] = 6       # change value of [0] via $a
">$a<"
">$b<"          # change is reflected in $b

$b += 40        # make $b refer to a new array
$a[0] = 8       # change value of [0] via $a
">$a<"
">$b<"          # change is not reflected in $b

次がパイプラインに書き込まれます。

>10 20 30<
>10 20 30<
>6 20 30<
>6 20 30<
>8 20 30<
>6 20 30 40<

9.6 配列要素としての配列

配列の要素自体を配列にすることができます。 たとえば、次のように入力します。

$colors = "red", "blue", "green"
$list = $colors, (,7), (1.2, "yes") # parens in (,7) are redundant; they
                                    # are intended to aid readability
"`$list refers to an array of length $($list.Length)"
">$($list[1][0])<"
">$($list[2][1])<"

次がパイプラインに書き込まれます。

$list refers to an array of length 3
>7<
>yes<

$list[1] は、次に示すように、$list[1][0] を介してアクセスされる整数 7 である 1 要素の配列を参照します。 これを、次の若干異なるケースと比較しましょう。

$list = $colors, 7, (1.2, "yes") # 7 has no prefix comma
">$($list[1])<"

ここで、$list[1] はスカラー、つまり $list[1] を介してアクセスされる整数 7 を参照します。

次の例を確認してください。

$x = [string[]]("red","green")
$y = 12.5, $true, "blue"
$a = New-Object 'object[,]' 2,2
$a[0,0] = $x               # element is an array of 2 strings
$a[0,1] = 20               # element is an int
$a[1,0] = $y               # element is an array of 3 objects
$a[1,1] = [int[]](92,93)   # element is an array of 2 ints

9.7 負の添字

これについては、§7.1.4.1 で説明します。

9.8 境界チェック

これについては、§7.1.4.1 で説明します。

9.9 配列スライス

配列スライス は、その要素がコレクションからの 0 個以上の要素のコピーである、制約のない 1 次元配列です。 配列スライスは添字演算子 [] (§7.1.4.5) を使用して作成されます。

9.10 配列のコピー

メソッド [Array]::Copy を使用して、連続する要素セットを配列間でコピーできます。 たとえば、次のように入力します。

$a = [int[]](10,20,30)
$b = [int[]](0,1,2,3,4,5)
[Array]::Copy($a, $b, 2)        # $a[0]->$b[0],
$a[1]->$b[1]
[Array]::Copy($a, 1, $b, 3, 2)  # $a[1]->$b[3],
$a[2]->$b[4]

9.11 配列の列挙

添字演算子を使用して各要素にアクセスする配列をループ処理することもできますが、foreach ステートメントを使用してその配列の要素を列挙できます。 多次元配列の場合、要素は行優先の順序で処理されます。 たとえば、次のように入力します。

$a = 10, 53, 16, -43
foreach ($elem in $a) {
    # do something with element via $e
}

foreach ($elem in -5..5) {
    # do something with element via $e
}

$a = New-Object 'int[,]' 3, 2
foreach ($elem in $a) {
    # do something with element via $e
}

9.12 多次元配列のフラット化

多次元配列に対する一部の操作 (レプリケーション (§7.6.3) や連結 (§7.7.3) など) では、配列を フラット化する 必要があります。つまり、制約のない型の 1 次元配列に変換されます。 結果の配列は、すべての要素を行優先の順序で受け取ります。

次の例を確認してください。

$a = "red",$true
$b = (New-Object 'int[,]' 2,2)
$b[0,0] = 10
$b[0,1] = 20
$b[1,0] = 30
$b[1,1] = 40
$c = $a + $b

$c で指定された配列には、要素 "red"、$true、10、20、30、40 が含まれます。