2011/03/25
ジャグ配列も、多次元配列も、あるんだよ
PowerShellは一次元のobject配列を多用しますが、実は他言語と同様に、多次元配列やジャグ配列(配列の配列)もちゃんとあります。
ジャグ配列
ジャグ配列の作成
PS > $array = @(@("a","b"),@("c","d","e"))
配列の参照
PS > $array a b c d e PS > $array.Length 2 PS > $array[0] a b PS > $array[0][1] b
ジャグ配列の作成は、配列をまず作って、その配列を要素に持つ配列を作成するとできます。とても直感的かと思います。ただしここで注意しなければならない点は、
PS > $array = @(@("a","b") + @("c","d","e"))
のように、配列を+演算子で連結するのは駄目であるという点です。こうしてしまうと単に一次元配列同士が連結された要素数5の一次元配列が生成されてしまいます。
さて、このようにジャグ配列に含まれる配列とその数があらかじめ分かっている場合はこのように,演算子を使えば問題ありませんが、そうではない場合はちょっと工夫が必要です。たとえば「テキストファイルの一行ごとにchar[]配列を作り、それらを要素に持つジャグ配列を作成する」ことを考えてみましょう。まず最初に駄目な例。
$lines = @(Get-Content file.txt) $array = @() foreach($line in $lines) { $array += [char[]]$line }
これは一見うまくいきそうですが、先ほどと同じパターンで$arrayは単なるchar[]の一次元配列になってしまいます。目的のジャグ配列を得るには次のようにします。
$lines = @(Get-Content file.txt) $array = @() foreach($line in $lines) { $array += ,[char[]]$line }
ここでは配列要素の追加処理の際、配列に「,」を前置することによって「配列要素を展開することなく、配列そのものとして扱う」ようにしています。こうすることで$arrayにはchar[]配列そのものが要素として追加され、結果としてジャグ配列が格納されます。
多次元配列
2x2の多次元配列を作成
PS > $array = New-Object "object[,]" 2,2
要素に値を代入
PS > $array[0,0] = "a" PS > $array[0,1] = "b" PS > $array[1,0] = "c" PS > $array[1,1] = "d"
配列の参照
PS > $array a b c d
配列のスライス
PS > $array[@(0,0)] a PS > $array[@(0,0),@(0,1)] a b PS > $array[@(0,0),@(1,0)] a c
配列の作成の仕方がちょっと気持ち悪いですが、これはサイズ固定の一次元配列を作るときと同じ要領です。
配列のスライスも可能で、切り出したい要素のインデックスを「要素のインデックスを表す配列」で指定します。たとえば$array[0,0]を取り出したい場合は$array[@(0,0)]になるわけですね。複数の要素を切り出したい場合は「要素のインデックスを表す配列」の配列(つまりはジャグ配列)を指定することになります。
おまけ:一次元配列のちょっとしたtips
変数、プロパティ、コマンドレットの戻り値などで、その値が配列かそうでないかが事前に分からない場合でも、必ず配列として処理したい場合には@を用います。
$lines = Get-Content file.txt
Get-Contentコマンドレットはテキストファイルが1行の場合は、$linesには文字列の配列ではなく文字列が格納されます(複数行なら行ごとの文字列が格納された配列になる)。よってこの場合$linesが配列かどうかは事前には分からないことになります。テキストファイルの1行目を取得するつもりで $lines[0] とやっても、もしテキストファイルが1行だった場合は、その1行の一文字目が返ってきてしまいます。このような事態を防ぐには、
$lines = @(Get-Content file.txt)
のようにすると、$linesには必ず配列が格納されます。たとえテキストファイルが1行でも、要素数1の配列になります。
これとは逆のケースで、「配列か非配列かわからないが、必ず非配列として扱いたい」場合は次のようにするのも手でしょう。
$value = @($unknown)[0]
この場合だともし$unknownが配列だったとしても、その1要素目をとってきて$valueに格納してくれます。本来なら$unknownが配列かどうか確かめて、その要素数がいくつであるかなどを確認すべきなんですが、「非配列か要素数1の配列どちらかが返されるパターン」というのはADSIやXMLなど扱う際に意外と多くて、そういう場合に有用かと思います。
JavaScriptの配列操作と同じようなことをする方法
$array = @(1..5) # push(配列末尾に値を追加) $array += 6 # unshift(配列先頭に値を追加) $array = @(0) + $array # shift(配列先頭の値を削除) $array[0]; $array = $array[1..($array.length-1)] # pop(配列末尾の値を削除) $array[$array.length-1]; $array=$array[0..($array.length-2)]元記事:http://blogs.wankuma.com/mutaguchi/archive/2011/03/25/197857.aspx
プライバシーポリシー