PowerShell 要素が1つの多次元配列を作る

17912 ワード

はじめに

2次元配列を渡す関数を作っていたのですが、要素が1つの場合に引数をうまく渡せませんでした。
なぜならば、要素が1つの多次元配列を上手く作れなかったからです。
Pythonで表すと以下のような場合です。

python
l = [[1,2,3]]

解決策は簡単なのですが、関数側で処理をするのではなく、配列を作る(関数に値を渡す)時に気を付けなければいけないので忘れそうです。
そのため、要素が1つの多次元配列を作る方法を記事にしてみます。

結論

とりあえずの結論は、以下のように"Comma operator"(,)を使えば作成できます。

powershell
$a = @(,@(1,2,3))
$a = (,(1,2,3))
$a = ,@(1,2,3)
$a = ,(1,2,3)

環境

> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      7.2.3
PSEdition                      Core
GitCommitId                    7.2.3
OS                             Microsoft Windows 10.0.22000
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

解説

配列の作成

1次元の配列を作る場合は、以下のようにします。

powershell
$a = @(1,2,3)
$a.GetType().BaseType.Name # Array OK
$a = (1,2,3)
$a.GetType().BaseType.Name # Array OK
$a = 1,2,3
$a.GetType().BaseType.Name # Array OK

要素が1つの1次元の配列の場合は、以下のようにします。
"Array subexpression operator"(@( ))を使っておけば良いと思います。
"Comma operator"(,)でも作成できますが、久しぶりに見ると混乱しそうです。

powershell
$a = @(1)
$a.GetType().BaseType.Name # Array OK
$a = ,(1)
$a.GetType().BaseType.Name # Array OK
$a = ,1
$a.GetType().BaseType.Name # Array OK

当たり前ですが、以下のように書くと配列にはなりません。

powershell
$a = (1)
$a.GetType().BaseType.Name # ValueType NG

配列の表示

この先で使うので配列を文字列にして表示する方法を念のため示しておきます。

powershell
$a = @(1,2,3)
Write-Host "$a" # "1 2 3"

もし、区切り文字を空白文字以外にしたい場合は、以下のようにします。

powershell
$a = @(1,2,3)
$ofs = ", "
Write-Host "$a" # "1, 2, 3"

終わったら$ofsはデフォルト値の空白文字にしておくほうがマナーは良さそうです。

powershell
$ofs = " "

多次元配列を作る

表示用関数

表示のための関数を定義しておきます。

powershell
function print {
  param (
    [Parameter(Mandatory)][Array] $array
  )
  $ofs = ", "
  $i = 0
  Write-Host $array.GetType().BaseType.Name
  foreach ($item in $array) {
    Write-Host ("{0} : {1} = {2}" -f $i++, "$item", $item.GetType().BaseType.Name)
  }
  Write-Host
  $ofs = " "
}

要素が2つの2次元配列

まずは、要素が2つの2次元配列を作ってみます。
記述方法を変えても同じものが出来ています。

powershell
$a = @(@(1, 2, 3), @(4, 5, 6))
print $a
$a = ((1, 2, 3), (4, 5, 6))
print $a
$a = @(1, 2, 3), @(4, 5, 6)
print $a
$a = (1, 2, 3), (4, 5, 6)
print $a

要素が1つの2次元配列

では、本題の要素が1つの2次元配列を作ってみます。
ほかのプログラム言語の感覚では、以下のようにすれば作成できそうですが上手くいきません。
1次元配列(1つ目の要素が数字)として扱われてしまいます。

powershell
$a = @(@(1, 2, 3))
print $a
$a = ((1, 2, 3))
print $a

どうすれば良いかと言うと、"Comma operator"(,)を使い以下のようにします。

powershell
$a = @(,@(1, 2, 3))
print $a
$a = (,(1, 2, 3))
print $a
$a = ,@(1, 2, 3)
print $a
$a = ,(1, 2, 3)
print $a

こうすれば、2次元配列(1つ目の要素が配列)として扱われます。

最後に

"Comma operator"(,)を使えば、要素が1つの多次元配列を作ることが出来ます。
ただ、先頭に付けなければいけないので混乱しそうです。

また、"Array subexpression operator"(@( ))を省略しても作成できてしまいます。
どれか1つに統一したほうが良さそうですので、以下のように統一しようかと思っています。

$a = @(1, 2, 3)
$a = @(,@(1, 2, 3))

参考