やりたかったこと
powershellで、Rubyのeach_cons
を実装してみたかった。
こんなイメージを目指していました
Get-EachCons -Count 2 -Array @(1,2,3) #=> @(@(1,2), @(2,3))
Get-EachCons -Count 2 -Array @(1,2) #=> @(@(1,2))
やったこと
PowerShellの配列が気持ち悪いのは、下記記事を読んで重々承知の上で、こんなコードを書いてみました。
参考: そろそろ PowerShell の一次配列の罠と回避について一言いっておくか - tech.guitarrapc.cóm
function Get-EachCons {
param($Count, $Array)
$size = ($Array | measure).Count
$outer = (0..($size - $Count)) | ForEach {
$i = $_
$inner = (0..($Count - 1)) | ForEach { $Array[$i + $_] }
# $retが単数だと勝手に単数に型変換するので
@(, $inner)
}
# @(@())を勝手に@()に変換してくれるので
@(, $outer)
}
PS> $cons = Get-EachCons -Count 2 -Array (1,2,3)
PS> $cons #=> @(@(1,2),@(2,3)) のつもり
1
2
2
3
PS> $cons[0] #=> @(1,2) のつもり:OK
1
2
ここまでは記事通りうまくいきました。
うまくいかなかったこと
で、ここからが本題。
配列を、1つだけ配列にいれると…
PS> $cons = Get-EachCons -Count 2 -Array (1,2)
PS> $cons #=> @(@(1,2)) のつもり
1
2
PS> $cons[0] #=> @(1,2) のつもり:NG
1
いやいやまさかそんなことはないはず…
sample code で検証
ここまでは先程の記事に触れられていた通り、うまくジャグ配列として取得できたのですが…
PS> $foo = @(, @(1,2))
PS> $foo #=> @(@(1,2)) のつもり
1
2
PS> $foo[0] #=> @(1,2) のつもり: OK
1
2
同じジャグ配列を関数に定義してあげると、なぜか1次元配列に元通り。
PS> function bar { @(, @(1,2)) }
PS> $bar = bar
PS> $bar #=> @(@(1,2)) のつもりだが、実は @(1,2)
1
2
PS> $bar[0] #=> @(1,2) のつもり:NG
1
結論?(というよりあきらめ)
もうこれはList<T>
を使えというお達しなのでしょうか…
こんなモジュールも用意されているようですし…
PowerShell で System.Collection.Generics.List を扱ってみる - tech.guitarrapc.cóm
うーん…
2016/10/5 add: 検証を別記事に起こしました。
(タイトル変更) powershell: 2次元配列とパイプの罠