目標
例えば、ある変数が空であるか判定するには以下のようになるが、
If (Var != Blank)
{
msgbox, , , 変数Varは空ではありません
}
変数ではなく配列だったらどうすればよいだろうか。
AutoHotKeyにおける配列とは
AutoHotKeyの配列はオブジェクトの一種で、object
という名称のオブジェクトである。オブジェクトがゲシュタりそう。
添え字が整数インデックスの配列、および添え字が文字列キーの連想配列が可能である。
ある配列は、整数インデックスを持つ要素と文字列キーを持つ要素の、両方を格納することができる。
対象(の文字列?)がオブジェクトであるかどうかは、IsObject()関数で判定できる。
配列の内容は、添え字を含めて全く不明とする。
要素数を得る/1つ目の要素を取り出す
配列オブジェクトに格納されている要素数は、通常length
メソッドで得られる。
; 配列の要素数が0より大きければループ処理
if (Array.length() > 0)
{
for, index, value in Array
{
msgbox, , , %index%: %value%
}
}
ただし、これは整数インデックスの要素のみがカウントされる。文字列キーを持つ要素はカウントされない。
(よって、対象の配列が整数インデックスのみを持つとわかっているなら(例えばスクリプトの引数が格納される配列A_Args
など)話はこれで終わり。)
例えば、以下の例ではArray.length()
は1になる。
Array := Object(1,"a","2","b") ; bは文字列キーを持つ要素
MsgBox, , , % Array.length()
つまり、ある配列の要素が文字列キーを持つなら、length
メソッドでは正しい要素数を得られない。
配列の1つ目の要素が取り出せるなら、空でないと判定できるように思われる。
MsgBox, , , % Array[1]
のように個々の要素にアクセスすることもできるが、「配列全体の中での要素の順番(整数)」ではなく、「ある要素が持つ整数インデックスまたは文字列キー」を指定する必要がある。よって、配列の1つ目の要素を確実に取り出すことはできない。
結局For
ループなんだよなあ
このような場合、For
ループを行えば、確実に1つ目の要素を取り出すことができる。1回以上ループできれば空ではないということ。
配列が1つも要素を持たない場合、ループは行われない。
for, key, value in Array
{
msgbox, , , 配列は空ではありません
Break
}
もちろん、正確な要素数を得ることもできる。
length = ; 変数を初期化
for, key, value in Array
{
length += 1
}
……というか、そんなことはわかりきってるので他の方法を探したのだが、やっぱり無かった。
配列だか連想配列だかその混合だかもわからないオブジェクトの要素へ確実にアクセスするには、とにかくFor
ループ。それから、1つ目だけ取り出すなら即Break
とか工夫すればいい。
配列が空であるか判定する関数
真偽値を返す。(Return - AutoHotkey Wiki)
パラメータが配列でなければ、偽を返し、かつErrorLevel
をVar
とする。
; 真=1 偽=0
IsArray(Target) {
If not (IsObject(Target))
{
ErrorLevel = Var
Return, 0
}
For, key, value in Target
Return, 1
; ループだが1回めでReturnするため2回め以降は実行されない
Return, 0
}
これで、変数と同じように簡単に判定できる。
If (IsArray("Array"))
{
msgbox, , , 配列Arrayは空ではありません
}