LoginSignup
2
2

More than 1 year has passed since last update.

PowerShell 第3回 二次元配列を他の関数に引き渡す

Last updated at Posted at 2021-07-05

はじめに

二次元配列を他の関数の引数にしようと思ったところ、かなりつまづきました。
二次元配列を参照しようとしているのに、一次元配列の参照しているようになります。
ArrayList[1,2]のようなときに、ArrayListが二次元配列のつもりで参照しているのに、一次元配列になって、その1番目と2番目の値を参照してしまいます。
くわしい結果はこちら
ネットを調べた結果答えはわかったので、自分の備忘のために記載します。

今回実施する内容

1つ目の関数の戻り値の二次元配列を2つ目の関数の引数にして、2つ目の関数で利用します。

ソースコード(Git Hub)

PowerShell_03_DimArrayList

環境

OS: Windows 10 JP (64bit)
PowerShell version: 5.1.19041.1023

参考

Powershell:関数の戻り値としての多次元配列 - powershell、多次元配列、戻り値
これがネットで調べた二次元配列を引数にする内容の記事です。

Microsoft Powershell about_Operators コンマ演算子
コンマ演算子,についての説明です。

用語

なし

二次元配列を他の関数に引き渡す

ポイントは、引き渡し元のコンマ演算子,です。ソースコードでは、最後の,$DimArrayListの部分です。
たったこれだけなんです。

ソースコード

DimArrayList_success.ps1
function CreateArrayList {
    $DimArrayList = New-Object "Object[,]" 2,2

    $DimArrayList[0,0] = 1
    $DimArrayList[0,1] = "No.1"
    $DimArrayList[1,0] = 2
    $DimArrayList[1,1] = "No.2"

    Write-Host "CreateArrayList"
    Write-Host $DimArrayList[0,0]
    Write-Host $DimArrayList[0,1]
    Write-Host $DimArrayList[1,0]
    Write-Host $DimArrayList[1,1]

    ,$DimArrayList
}

function ReferArrayList {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [Object[,]]$DimArrayList
    )
    Write-Host "ReferArrayList"
    Write-Host $DimArrayList[0,0]
    Write-Host $DimArrayList[0,1]
    Write-Host $DimArrayList[1,0]
    Write-Host $DimArrayList[1,1]

    $newDimArrayList = New-Object "Object[,]" 2,2
    $newDimArrayList = $DimArrayList
    Write-Host "newDimArrayList"
    Write-Host $newDimArrayList[0,0]
    Write-Host $newDimArrayList[0,1]
    Write-Host $newDimArrayList[1,0]
    Write-Host $newDimArrayList[1,1]
}

try {
    $ArrayList = CreateArrayList
    ReferArrayList $ArrayList
} catch {
    Write-Host $Error[0]
}

実行結果

CreateArrayList
1
No.1
2
No.2
ReferArrayList
1
No.1
2
No.2
newDimArrayList
1
No.1
2
No.2

CreateArrayList関数の説明

CreateArrayList関数における二次元配列の生成

$DimArrayList = New-Object "Object[,]" 2,2
の記載でObjectの2x2の二次元配列を作ります。動的配列でもよいのですが、今回は宣言で作成します。
Objectなのは意味はありません。私の用途ではObjectにしたかっただけです。

CreateArrayList関数のコンマ演算子

そのあとは作成した$DimArrayListに値を代入して、本関数内でコンマ演算子,を使って出力しています。

コンマ演算子の説明

Microsoft Powershell about_Operators コンマ演算子の内容を引用します。

コンマ演算子 ,
二項演算子として、コンマは配列を作成するか、作成される配列にを追加します。 式モードでは、単項演算子として、コンマは1つのメンバーだけで配列を作成します。 メンバーの前にコンマを配置します。

PowerShell
$myArray = 1,2,3
$SingleArray = ,1
Write-Output (,1)

Write-Objectでは引数が想定されているため、式をかっこで囲む必要があります。

何を言っているのかよくわかりませんでしたが、この部分が今回の解決策のポイントと理解しました。

式モードでは、単項演算子として、コンマは1つのメンバーだけで配列を作成します。 メンバーの前にコンマを配置します。

コンマ演算子,を付けない場合$DimArrayListで関数の戻り値を返すと、この時点で二次元配列ではなくなり、1, No.1, 2, No.2の順で、戻っていくようです。
これはパイプライン処理のための動作と考えるとそうかと合点が来ました。
Powershellでは、戻り値をreturnで返すような仕様ではなく、処理の中でどんどん値が戻っていく動作です。これはPowershellをやられている方ならばわかる仕様だと思いますが、これを防ぎたい場合はそれなりの書き方をしてきたわけですが、配列を渡す場合もどんどん戻っていくんだなと考えたら、合点が来たということです。
これをコンマ演算子,を付けることで、配列をまとめて1つとして戻すということです。
VBSとかJavaScriptとかJavaとかCとかやってきた私としては、変数なんだから1つを返すでしょうと思っていたのですが、パイプライン処理にまたしてもやられました。

ReferArrayList関数の説明

特段説明する箇所はないのですが、[CmdletBinding]で、引数の定義を行っています。
ここで引数の型として、[Object[,]]として、二次元配列にします。

そのあとのWrite-Hostは値を参照しているだけです。

$newDimArrayList = New-Object "Object[,]" 2,2以降については、**コンマ演算子,のことがわからずに、どうしたら引き渡せるのか?のトライアルとして、「改めて二次元配列を定義して、引数を入れてみたらどうか?」と考えて実施してみたものの形跡です。ですので、実際には不要な記載です。

失敗例

うまくいかないと思って記載していたソースコードは以下です。違いは、コンマ演算子,の有無だけです。

DimArrayList_fail.ps1
function CreateArrayList {
    $DimArrayList = New-Object "Object[,]" 2,2

    $DimArrayList[0,0] = 1
    $DimArrayList[0,1] = "No.1"
    $DimArrayList[1,0] = 2
    $DimArrayList[1,1] = "No.2"

    Write-Host "CreateArrayList"
    Write-Host $DimArrayList[0,0]
    Write-Host $DimArrayList[0,1]
    Write-Host $DimArrayList[1,0]
    Write-Host $DimArrayList[1,1]

    $DimArrayList
}

function ReferArrayList {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [Object[,]]$DimArrayList
    )
    Write-Host "ReferArrayList"
    Write-Host $DimArrayList[0,0]
    Write-Host $DimArrayList[0,1]
    Write-Host $DimArrayList[1,0]
    Write-Host $DimArrayList[1,1]

    $newDimArrayList = New-Object "Object[,]" 2,2
    $newDimArrayList = $DimArrayList
    Write-Host "newDimArrayList"
    Write-Host $newDimArrayList[0,0]
    Write-Host $newDimArrayList[0,1]
    Write-Host $newDimArrayList[1,0]
    Write-Host $newDimArrayList[1,1]
}

try {
    $ArrayList = CreateArrayList
    ReferArrayList $ArrayList
} catch {
    Write-Host $Error[0]
}

失敗例の実行結果

CreateArrayList
1
No.1
2
No.2
ReferArrayList
1 1
1 No.1
No.1 1
No.1 No.1
newDimArrayList
1 1 
1 No.1
No.1 1
No.1 No.1

おわりに

PowerShellなかなか難しいです。
当たり前と思っている動作が、当たり前に動作しない。
なかなかなじんでこないです。本当に難しい。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2