ActionScript 3.0で始めるオブジェクト指向スクリプティング

第56回 【特別編】配列エレメントすべてをforループで扱う

この記事を読むのに必要な時間:およそ 3.5 分

Array.push()メソッドよりも配列アクセスが速いのは

つぎは,Array.push()メソッドよりも,配列アクセス演算子[]でエレメントを加える方がなぜ速いのかだ。Array.push()メソッドは,[ヘルプ]につぎのように説明されている。

エレメントを配列の最後に追加して,追加後の配列の長さを返します。

ここでまた,Flash Playerの立場で仕事を考える。すると,Array.push()メソッドで配列エレメントを加えるには,配列の最後尾を探さなければならないことに気づく図3⁠。具体的には,Array.lengthプロパティの値を調べることになる。それに対して,配列アクセスを使うときには,エレメントを加えるべきインデックスが演算子[]にはっきりと示されていなければならない。つまり,最後尾を探す手間がないのだ。

図3 配列の最後尾を探さないとけいない

図3 配列の最後尾を探さないとけいない

このようにFlash Playerの立場で考えることは,ただおまじないのように最適化テクニックを覚えるのと違い,ActionScript 3.0の処理をより深く知ることにつながる。結果に至る筋道がわかれば,別の処理についても推論できる。

たとえば,予め長さが決められない配列にエレメントを加えたいとする。エレメントは配列アクセス演算子[]で加える方が速いといった。すると,配列が変数my_arrayに納められている場合,このように書くことになろう。

my_array[my_array.length] = エレメント;

しかし,このステートメントの処理は,Array.push()メソッドを使った場合と比べて速さはほぼ変わらない。勘のよい読者は,Array.lengthプロパティで最後尾を調べているからだということに気づかれたと思う。⁠配列アクセス演算子[]の処理そのものは,別に速くない」と前に述べたのは,つまりこのような意味である。

エレメントのインデックスはuint型で渡す

結びは,配列アクセス演算子[]に渡すインデックスについての注意だ。インデックスは必ずuint型にしよう。そんなことはわかりきっていると思われるかもしれない。しかし,こういう場合はどうだろう。ある配列のエレメントを,インデックスが偶数と奇数のふたつの配列に分ける。たとえば,つぎのような配列(my_array)だ。

var my_array:Array = [0, 1, 2, 3, 4, 5];
    
・インデックスが偶数のエレメントの配列: [0, 2, 4]
・インデックスが奇数のエレメントの配列: [1, 3, 5]

もとの配列(my_array)の長さArray.lengthプロパティ値)が必ず偶数なら,つぎのようなスクリプトが考えられる。動作に問題はなく,エレメントは奇数と偶数のインデックスに分けられて,ふたつの配列(even_arrayとodd_array)ができあがる図4⁠。

var my_array:Array = [0, 1, 2, 3, 4, 5];
var nLength:uint = my_array.length / 2;
var even_array:Array = [];
var odd_array:Array = [];
for (var i:uint = 0; i < nLength; i++) {
  even_array[i] = my_array[i * 2];
  odd_array[i] = my_array[i * 2 + 1];
}

図4 ひとつの配列をインデックスが偶数と奇数のふたつの配列に分ける

図4 ひとつの配列をインデックスが偶数と奇数のふたつの配列に分ける

図4 ひとつの配列をインデックスが偶数と奇数のふたつの配列に分ける

forループで用いるカウンタ変数(i)はuint型で定めた。しかし,偶数と奇数の配列インデックスを求めるため,その変数に乗算と加算を行っている。そうすると,計算結果には型指定が及ばなくなる。したがって,最適化するためには,式全体をuint()関数の引数に渡し,整数に変換した方がよい※1⁠。

var my_array:Array = [0, 1, 2, 3, 4, 5];
var nLength:uint = my_array.length / 2;
var even_array:Array = [];
var odd_array:Array = [];
for (var i:uint = 0; i < nLength; i++) {
  even_array[i] = my_array[uint(i * 2)];
  odd_array[i] = my_array[uint(i * 2 + 1)];
}

この特別編の次回(第58回)は,スクリプトのアニメーションとオブジェクトの使い回しテクニックを紹介するつもりだ。

※1)
あるいは,式の値を一旦uint型の変数に入れるのでもよい。
var n:uint = i * 2;
even_array[i] = my_array[n];

著者プロフィール

野中文雄(のなかふみお)

ソフトウェアトレーナー,テクニカルライター,オーサリングエンジニア。上智大学法学部卒,慶応義塾大学大学院経営管理研究科修士課程修了(MBA)。独立系パソコン販売会社で,総務・人事,企画,外資系企業担当営業などに携わる。その後,マルチメディアコンテンツ制作会社に転職。ソフトウェアトレーニング,コンテンツ制作などの業務を担当する。2001年11月に独立。Web制作者に向けた情報発信プロジェクトF-siteにも参加する。株式会社ロクナナ取締役(非常勤)。

URLhttp://www.FumioNonaka.com/

著書