スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

カテゴリ : スポンサー広告

TJS小ネタ - foreach

tjsの小ネタ。駄文。foreachの解説。

配列を順に処理するには↓のようにforで添え字をまわします。
var array = [0102030405060708090];

for (var i = 0; i < array.count; i++) {
    Debug.message(array[i]);
}
配列arrayの中身を順にDebug.message関数でコンソールに表示するだけのスクリプトです。
0, 10, 20, ..., 90まで表示されます。

ついでに逆順に処理する例
var array = [0102030405060708090];

for (var i = array.count-1; i >= 0; i--) {
    Debug.message(array[i]);
}
先ほどとは逆に90, 80, 70, ..., 0まで表示されます。


foreachの使い方(1)
辞書配列でもおなじように順に処理したい場合はどうするか。
KAGEXのUtils.tjsにそのためのの関数としてforeach関数が定義してあります。
以下該当部分をコピペ。
/**
 * 辞書の総なめ処理
 * @param dict 辞書
 * @param func 処理ファンクション func(name, value, dict);
 */

function foreach(dict, func, *) {
    if (dict) {
        var names = [];
        names.assign(dict);
        for (var i = 0; i < names.count; i += 2) {
            func(names[i], names[i+1], dict, *);
        }
    }
}
第1引数dictに処理したい辞書配列をわたします。
第2引数funcに辞書配列のそれぞれのペアを処理する関数をわたします。

とりあえず使ってみます。
/* スクリプト例(1) */

// 適当な辞書配列
var hoge = %[
    "first" => 1,
    "second" => 2,
    "third" => 3,
];

// 処理関数
function fuga(name, value, dict) {
    Debug.message("dict[" + name +"] の中身は「" + value + "」です。");
}

// foreachを使う
foreach(hoge, fuga);
これを実行すると以下のように表示されます。
dict[first] の中身は「1」です。
dict[second] の中身は「2」です。
dict[third] の中身は「3」です。
foreachの第2引数にわたした関数(ここではfuga関数)にはいくつか引数がわたされます。
第1引数(name)に添え字の名前が、第2引数(value)にはそれに対応する値がわたされます。
第3引数(dict)は使っていませんが、foreachの第1引数にわたした辞書配列がそのままわたされています。
第1引数と第2引数の内容が順に変わりながら、辞書配列のペアの数だけfuga関数が呼ばれます。
fuga("first"1, hoge);
fuga("second"2, hoge);
fuga("third"3, hoge);
というのを勝手にやってくれるのがforeach関数です。

foreachの使い方(2)
第3引数まではforeachの定義で決められていますが、第4引数以降には好きな引数をわたすことができます。
foreachの第3引数以降にわたしたものが、第4引数以降にそのままわたされます。

以下使ってみるスクリプト。
/* スクリプト例(2) */

// 適当な辞書配列
var hoge = %[
    "first" => 1,
    "second" => 2,
    "third" => 3,
];

// 処理関数
function fuga(name, value, dict, test1, test2) {
    Debug.message("dict[" + name +"] の中身は「" + value + "」です。");
    Debug.message("第4引数の値は:" + test1 + ", 第5引数の値は:" + test2);
    // ↑Debug.messageをもう1行追加
}

// foreachを使う
foreach(hoge, fuga, "test1にわたる値""test2にわたる値");
// ↑第3引数以降にも値をわたす
変更点は、
・関数fugaに引数test1とtest2を追加し、Debug.messageで表示するようにする。
・foreachの第3引数と第4引数に文字列をわたすようにする。
の2点のみです。

これを実行すると以下のように表示されます。
dict[first] の中身は「1」です。
第4引数の値は:test1にわたる値, 第5引数の値は:test2にわたる値
dict[second] の中身は「2」です。
第4引数の値は:test1にわたる値, 第5引数の値は:test2にわたる値
dict[third] の中身は「3」です。
第4引数の値は:test1にわたる値, 第5引数の値は:test2にわたる値

ここではforeachは以下のように処理関数fugaを呼び出しています。
fuga("first"1, hoge, "test1にわたる値""test2にわたる値");
fuga("second"2, hoge, "test1にわたる値""test2にわたる値");
fuga("third"3, hoge, "test1にわたる値""test2にわたる値");


実際にKAGEXで使われている部分を見るとhogeの部分は式中関数としてわたされていることが多いです。
見た目としては↓のようになります。
/* スクリプト例(3) */

// 適当な辞書配列
var hoge = %[
    "first" => 1,
    "second" => 2,
    "third" => 3,
];

// foreachを使う
foreach(hoge, function(name, value, dict) {
    Debug.message("dict[" + name +"] の中身は「" + value + "」です。");
});
実行結果はスクリプト例(1)とおなじになります。

使い方の説明は以上です。次はforeachのスクリプトを解説します。

foreachの仕組み
行番号を振って再掲。
0: function foreach(dict, func, *) {
1:     if (dict) {
2:         var names = [];
3:         names.assign(dict);
4:         for (var i = 0; i < names.count; i += 2) {
5:             func(names[i], names[i+1], dict, *);
6:         }
7:     }
8: }
0行目はただの関数宣言です。
1つ目の引数dictは処理したい辞書配列、2つ目の引数funcは処理関数でした。
3つ目の引数の*は見慣れないかもしれません。
リファレンス参照→http://devdoc.kikyou.info/tvp/docs/tjs2doc/contents/function.html#id214
4行目を見るとfuncの第4引数に*が指定されています。
ここではforeachの第3引数以降をfuncの第4引数以降にわたす機能を果たしています。

1行目はdictがvoidのときには何もしない、程度だと思います。

2行目はnamesに配列を生成しています。

3行目でその配列にわたされた辞書配列dictをコピーしています。
リファレンス参照→http://devdoc.kikyou.info/tvp/docs/tjs2doc/contents/array.html#id14
辞書配列を配列にコピーすると、「名前、値の順に交互に現れる配列」になります。
例えば引数にわたされたdictが
dict["first"] = 1;
dict["second"] = 2;
dict["third"] = 3;
だったとき、配列namesは
names[0] = "first";  // ←1つ目のペアの名前
names[1] = 1;        // ←1つ目のペアの値
names[2] = "second"// ←2つ目のペアの名前
names[3] = 2;        // ←2つ目のペアの値
names[4] = "third";  // ←3つ目のペアの名前
names[5] = 3;        // ←3つ目のペアの値
のようになります。
添え字が偶数の部分にペアの名前、奇数の部分にペアの値が入っている形です。

4,5,6行目のforループで実際にわたされた処理関数funcを呼び出します。
最初のループではi=0です。
このとき「func(names[0], names[1], dict, *);」として呼びだされます。
names[0]="first", names[1]=1だったので使い方の欄で説明したとおりに引数がわたされています。
次のループに入るときにはiに2を足すことで次のペアをわたしてfuncを呼び出します。
2周目のループでは「func(names[2], names[3], dict, *);」となるわけです。
これを最後のペアまで繰り返します。
スポンサーサイト

タグ : 吉里吉里 KAGEX TJS

カテゴリ : TJS

コメントの投稿

非公開コメント

最新記事
カテゴリ

openclose

記事一覧
Twitter
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。