JavaScript/配列
配列リテラル編集
配列リテラル(はいれつリテラル、array literal)は、要素を ,
で区切り全体を [ ]
で囲んで表します。最後の要素の ,
はあっても構いません。
C言語の配列のように、要素数を予め決め全ての要素の型が同じオブジェクトに型付き配列があります。
アラートのコード例
const ary = [ 'A', 'B', 'C', 'D', 'E' ];
alert( ary[2] ); // C
HTMLに組み込んだ場合
<!DOCTYPE html>
<html lang="ja">
<meta charset="utf-8">
<title>テスト</title>
<body>
テスト<br>
<script>
const ary = [ 'A', 'B', 'C', 'D', 'E' ];
document.write( ary[2] ); // C
</script>
</body>
</html>
結果 警告ダイアログボックスがポップアップし C と表示される。
別のコード例
const ary = [ 'A', 'B', 'C', 'D', 'E' ];
alert( ary[0] ); // A
alert( ary[1] ); // B
alert( ary[2] ); // C
alert( ary[3] ); // D
alert( ary[4] ); // E
alert( ary.length ); // 5
上記の配列の 'A' や 'B' などのように、配列の個々の成分のことを、その配列の要素(ようそ、element)と言います。
また、それぞれの要素にアクセスする際には、配列オブジェクトに続いてインデックス(index、添え字、添字、そえじ)を[ ]
で囲みます。インデックスは0から始まる整数です。
書式
配列オブジェクト[インデックス]
JavaScriptのインデックスは、(1ではなく)0から始まることに注意してください。(なお、C言語の配列も同様に0番目から数え始める方式です。)
よって、JavaScriptの配列の最後の要素のインデックスは、lengthプロパティで取得できる配列の長さ(要素数)よりも1小さくなります。
さて、JavaScriptでは1つの配列に異なるデータ型のオブジェクトを入れることができます。
const ary = [null, false, true, { a: 0, b: 1 }, 123, 3.14, 5n, [0, 1, 2], undefined];
alert(ary); // ,false,true,[object Object],123,3.14,5,0,1,2,
alert(ary[4]); // 123
alert メソッドや console.log メソッドだけでなく document.write
の引数などに配列を使うことも可能です。
<!DOCTYPE html>
<html lang="ja">
<meta charset="utf-8">
<title>テスト</title>
<body>
テスト<br>
<script>
const ary = [ 'A', 'B', 'C', 'D', 'E' ];
document.write( ary[0] ); // A
</script>
</body>
</html>
(※ 参考: ) 可変長編集
さて、JavaScriptでは、配列を宣言する際に、その要素数を宣言することはありませんでした(宣言することも出来ます)。
これはつまり、JavaScriptでは、配列の要素数をあとから更新することも可能だという事です。
たとえば
ary.length = 10;
と length プロパティに代入することにより、その配列の長さをたとえば 10 に変更することも可能です。
たとえば下記コードでは、もともと配列の長さは2ですので、 ary[2] は要素数を超えた参照です(0番から数えるので ary[2] は3番目です)。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>テスト</title>
</head>
<body>
テスト<br>
<script>
const ary = [ 'z', 'x' ]; // 長さは 2
document.write( ary[2] ); // 配列の長さを(1つ)超えた要素参照
</script>
</body>
</html>
このコードを実行すると
テスト undefined
と表示されます。
ですが、
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>テスト</title>
</head>
<body>
テスト<br>
<script>
const ary = [ 'z', 'x' ];
ary.length = 3; // 追加 (実は冗長;後述)
ary[2] = 'c'; // 追加
document.write( ary[2] +"<br>"); // c
// 確認
document.write( ary[1] +"<br>"); // x
document.write( ary[0] +"<br>"); // z
</script>
</body>
</html>
とすれば
テスト c x z
と表示されます。
なお
ary.length = 3;
の部分は無くても、配列の長さ変更することも可能です。
このように、配列の長さを自由に変えられる仕組みのことを「可変長」(動的配列)といいます。
一方、C言語の配列は、(可変長ではなく)固定長(静的配列)です。
疎な配列 |
配列の length プロパティを変更したり、大きなインデックスを使って要素の書き換えを行ったらどうなるでしょう。 let ary = [1, 2, 3];
ary.length = 10;
console.log(ary); // "1,2,3,,,,,,,"
console.log(ary[7]); // undefined
ary[6] = 99;
ary[8] = void 0;
ary[100] = "str";
delete ary[1];
ary.forEach((x,i) => console.log(`${i}: ${x}`));
// 0: 1
// 2: 3
// 6: 99
// 8: undefined
// 100: str
このように初期化されていない要素を持つ配列の要素の事を、疎な配列と言います。数学の疎行列(要素の殆どが 0 な行列)とは異なる概念なので字面に騙されないようにして下さい。 |
Array編集
Arrayオブジェクトのコンストラクタの引数は要素のリスト、もしくは配列の長さです。 Arrayは「アレイ」と読み、「配列」(はいれつ)という意味です。
配列の初期化は、次のようにして行います。
// [ 'A', 'B', 'C', 'D', 'E' ]
const ary = new Array( 'A', 'B', 'C', 'D', 'E' );
または
// [ 'A', 'B', 'C', 'D', 'E' ]
const ary = new Array(5); // [empty × 5]
ary[0] = 'A';
ary[1] = 'B';
ary[2] = 'C';
ary[3] = 'D';
ary[4] = 'E';
スプレッド構文編集
スプレッド構文を使うと、次のように書くことが出来ます。
// [ 'A', 'B', 'C', 'D', 'E' ]
const ary = new Array(..."ABCDE");
また、for文を使って、動的に値を代入することもできます。 以下の例では、それぞれ0から4が代入されます(1から5ではないことに注意)。
// [ 0, 1, 2, 3, 4 ]
const ary = new Array();
for (let i = 0; i < 5; i++){
ary[i] = i;
}
スプレッド構文と Arrray.prototype.map メソッドを組み合わせたトリック
// [ 0, 1, 2, 3, 4 ]
const ary = [...Array(5)].map((_, n) => n)
配列の反復処理編集
配列の要素を1つずつ取り出して処理するには、for文 (フォーぶん)を使用します。
// A1, B2, C3, D4, E5 を順番にアラート
const ary = [ 'A1', 'B2', 'C3', 'D4', 'E5' ];
for (let i = 0; i < ary.length; i++) {
const element = ary[i];
alert(element);
}
JavaScriptにかぎらず、プログラミングで繰り返し処理をしたい場合、for文というのを使うことが、よくあります。
JavaScript では、配列はオブジェクトとして扱われるので、 .length などのプロパティを持っています。なお 配列の .length プロパティは、その配列の要素数を数えます。なので、上記コード例の ary.length の中身は数値 5 です。
※ 配列で使用できるプロパティやメソッドについて詳しくは『JavaScript/Array』を参照。Arrayコンストラクタを使わずに配列リテラルで定義しても、これらのプロパティやメソッドを使用可能です。
// A, B, C, D, E を順番にアラート
const ary = [ 'A', 'B', 'C', 'D', 'E' ];
ary.forEach(function(element){
alert(element);
});
Array.prototype.forEachメソッドとアロー関数を使うとより簡素に書けます。
const ary = [ 'A', 'B', 'C', 'D', 'E' ];
ary.forEach(el => alert(el));
for-in文はオブジェクトのプロパティを順番に取り出す構文であり、配列オブジェクトに使用するとに配列の添字と追加されたプロパティのキーを反復対象にしてしまいます。
const ary = [..."abc"]; // [..."abc"] はスプレッド構文で ["a", "b", "c"] を返します。
ary.m = function(){};
for (const item in ary) {
console.log(item);
}
/*
0
1
2
m
*/
配列など反復構造の要素を順に反復したい場合は、for-of文を使います。
const ary = [..."abc"];
ary.m = function(){};
for (const item of ary) {
console.log(item);
}
/*
a
b
c
*/
Array.prototype.reduceメソッド編集
配列の中から最大値を探す編集
const a = []; //巨大配列を乱数で埋め尽くす
for (let i = 0; i < 999999; i++)
a[i] = Math.random() * 100;
console.log(a.reduce((a, b) => Math.max(a, b), -Infinity)); //reduceは出来る!
console.log(Math.max(...a)); // エラー! RangeError: Maximum call stack size exceeded
最小値・最大値・合計・総積を一度に求める編集
const a = [];
for (let i = 0; i < 100; i++)
a[i] = Math.random() * 100;
ans = a.reduce(({min, max, sum, infProd}, n) => {
min = Math.min(min, n);
max = Math.max(max, n);
sum += n;
infProd *= n;
return {min, max, sum, infProd};
}, {
min: Infinity,
max: -Infinity,
sum: 0,
infProd: 1,
});
console.log(`最小値 = ${ans.min}
最大値 = ${ans.max}
算術平均 = ${ans.sum/a.length}
幾何平均 = ${Math.pow(ans.infProd, 1/a.length)}
`);
配列の配列編集
配列の配列(はいれつのはいれつ、array of arrays)とは、配列を要素に含む配列です。二次元配列ともいいます。将棋盤のような2次元のデータ構造を表すのに用いられます。
const ary = [
[ 'A', 'B', 'C', 'D', 'E' ],
[ '0', '1', '2', '3', '4' ],
[ 'a', 'b', 'c', 'd', 'e' ],
[ 'V', 'W', 'X', 'Y', 'Z' ],
[ 'v', 'w', 'x', 'y', 'z' ]
];
alert( ary[0][0] ); // A
alert( ary[1][0] ); // 0
alert( ary[2][2] ); // c
alert( ary[3][2] ); // X
alert( ary[4][4] ); // z
n次元の配列 |n>=2| を一般にn-次元配列(n-dimensional array)、多次元配列(たじげんはいれつ、multidimensional array)などとも呼びます。プログラミング言語によっては、上記の例のように同じ次元の要素数がそろっている正方形の形をしたものを多次元配列、そうでない不規則なものをジャグ配列(ジャグはいれつ、jagged array)と呼んで区別することもありますが、JavaScriptでは特に区別しません。