配列と辞書配列

配列とは

数値とか文字列とか特定の値を格納するのに今までは変数を使ってきました。変数は必要あれば好きなだけ作ることができますが、量が多いと名前をつけるのがちょっと大変になってきます。

それに、場合によっては関連するものでまとめたい場合があります。

そういうときに使うのが配列です。変数の領域のイメージとしてロッカーの個々の箱の話をしましたが、配列はいわば、そのロッカーそのものに近いです。100個の箱があるロッカーがいくつもあって、ロッカーAの1番目の箱、2番目の箱……にそれぞれ数値とかを入れることができます。

TJSの場合、別に100個で制限があるわけではなく1000個でも10000個でもいくらでも増えていきます。他のことでもそうですが、現在のパソコンはパワフルですので少しくらい記憶させてもまったく負担になりません。変に恐縮する人がたまにいますが、最初はメモリ資源や処理速度のことなんかまったく考えず、どうやったらやりたいことができるかに集中してコーディングすることをおすすめします。

配列のサンプル

データ的にまとめることができるのはそうですが、それを数値で簡単にアクセスできるところにあります。

たとえば、学校でのテストの点の管理を考えてみます。

[iscript]
var taro = 78;
var hanako = 61;
var risa = 5;
// 平均点
var average = (taro + hanako + risa) / 3;
[endscript]

これが3人だから簡単です。非常に汎用性は乏しいですが。

次に students0, students1, ……といった変数名で管理する方法があります。若干汎用性は増しますが、せっかく数値で管理しているのに students1 の次は students2 であることをプログラムは察知してくれませんので、結局は全部記述しなければなりません。

同じく数値で管理する配列であれば

[iscript]
// 配列を代入
var students = new Array();
students[0] = 78;
students[1] = 61;
students[2] = 5;
// ……
// 生徒の数
var num = students.count;
// 平均点
var average = 0;
for(var i = 0; i < num; i++){
  // 一旦 average に全得点を格納
  average += students[i];
}
// 人数で割る
average /= num;
[endscript]

TJSの場合、0から1, 2, 3, ……といったように数値で管理され、簡単にアクセスできるようになっています。便利なところは、i++ したあと students[i] すると次の人の得点を参照できるため、for文などと組み合わせると非常にシンプルに書けます。

とりあえず得点の代入は逐一行っていますが、エクセルで管理したファイルをもとに、セルごとに代入していくなど発展させることもできます。

配列の作成

(かなりいいかげんな説明でいえば)数値と文字列以外のモノをオブジェクトといいます。

単純なデータではなく、複数のデータをまとめる配列の他、ウィンドウやレイヤなどすべてオブジェクトになります。TJSはオブジェクト指向の言語となっており、非常に多くのオブジェクトが扱われています。

とりあえず数値や文字列以外のオブジェクトでも同様に変数に代入し、参照できる特別なモノだという程度の認識で構いません。

しかし、配列であることを表すため、新しく作った配列を代入してやる必要があります(a)。もしくは、文字列をあらわす "abc" のように、配列をあらわす ["a", "b", "c"] をコード中に書くことができます。ですので空配列の [] を代入することで、その変数は配列ということになります。

var a = new Array();
var b = [];

count プロパティ

array.count で配列のサイズが返ってきます。配列はオブジェクトですので、このような状態を保持しているプロパティや、特定の操作を行うメソッドなどがいくつか用意されています。

その他のメソッドなどはTJS2リファレンス - Array クラスに載っています。

配列のコピー

配列は、文字列などのように参照し、代入することができます。

[iscript]
var array1 = new Array();
array[0] = "foo";
var string1 = "bar";

var array2 = array1;
array2[0] = string1;
var string2 = string1;
string2 += "baz";

// array1 => ["bar"]
// array2 => ["bar"]
// string1 => "bar"
// string2 => "barbaz"
[endscript]

数値や文字列の場合、代入した先(string2)で変更が行われたら、元(string1)とは無関係に変更されます。これは代入される際に、string1 の値を参照し string2 にその値を代入したからです。

しかし配列はオブジェクトであり、巨大なので普通に代入はできません。そこで配列自体の場所のみの情報が代入されます。つまり、array1 にはロッカーの場所が保持されており、array1[0] といわれたら array1 の場所にあるロッカーの最初の箱を見なさい。という意味となります。

ここで、array2 = array1 はロッカーの場所が書かれたメモをコピーしたにすぎません。そのため、array2[0] は array1[0] と同じ場所となり、結果、内容を上書きしちゃいました。

それを避けるには以下のようにします。

[iscript]
var array1 = new Array();
var array2 = new Array();
array1[0] = "foo";
// array1 を array2 にコピー
array2.assign(array1);
[endscript]

辞書配列

配列は数値でアクセスしましたが、辞書配列は文字列をキーにして管理する配列です。

var dic = new Dictionary();
dic["foo"] = "ふー";
dic["0"] = 0;
// 0 は "0" として扱われる→上書き
dic[0] = "ぜろ";
dic.bar = "ばー";
// dic.1 = "いち"; // 数値先頭は文法エラー

辞書配列へのアクセスの仕方は、直接メンバ選択演算子のドットを使った dictionary.member の形式と、間接メンバ選択演算子の大カッコを使った dictionary["member"] の形があります。一般的にドット演算子の方が楽なので、そちらを使うことが多いかと思われます。

ですが、ドット演算子の場合、member は先頭に数値をもってくることはできません。→TJS2リファレンス - トークン

また、間接メンバ選択演算子の場合、一旦カッコ内の演算が行われてからメンバを選択しますので、dictionary["mem" + "ber"] などでもアクセスができます。

KAGの変数と辞書配列

KAGシステムにおいて、用意されている3種類の変数があります。

どの変数も f.flag の形式で書かれ、好きなだけ増やすことができます。この sf, f, tf は辞書配列オブジェクトとなっていますので、「変数」とは一部性質が異なる部分があります。

具体的にいえば、宣言の部分。

変数は使う前に var キーワードで宣言を行ってから使う必要があります。しかし、辞書配列 sf など自体はそれにしたがっても、辞書配列の要素である sf.foo などには必要がありません。もっと言えばエラーとなります。

[iscript]
var foo;
// bar = 1; // エラー:宣言がない
foo = new Dictionary();
// var foo.bar = 1; // エラー:変数ではない
[endscript]

あくまで、dictionary.member は変数でなく、辞書配列 dictionary のメンバ(辞書配列要素)なのです。

KAGシナリオ上で変数を使いたい場合は、KAGシステムで使用されている変数名とのバッティングも考えられますので、基本的には用意されている sf, f, tf のメンバで対応するのが無難かと思います。ですので、var キーワードを用いるのは for 文でくらいなものでしょうか。

 
tjs/array.txt · 最終更新: 2008/09/15 07:37 by tohka