値には種類がある
これまでに、配列の作成方法や多次元配列の構造を確認してきました。
実際のプログラムでは、配列は作って終わりではなく、中身を変更したり、追加・削除したりしながら使われます。
JavaScriptでは、こうした操作を行うために配列専用のメソッドが用意されています。
ここでは、配列を扱ううえで基本となる操作方法を見ていきましょう。
配列に要素を追加する
配列に新しい要素を追加します。
これにより配列数も変動します。
構文
配列名.push('追加する要素');
配列名.unshift('追加する要素');
push・unshiftともにメソッドで、カッコ内には追加する要素を記述します。
追加する要素は、配列の型に合わせて記述します。
文字列の場合はシングルクォーテーションで囲み、数値の場合は不要です。
pushは配列の最後に、unshiftは配列の先頭に追加します。
コード例
//arrayAdd.js
const arr = ['りんご', 'みかん', 'いちご'];
arr.push('ぶどう');
alert(arr);
arr.unshift('メロン');
alert(arr);
alert(arr.length);
動作例
まず、pushでぶどうという文字列が配列の最後に追加されます。
最後に追加されていることがalertで確認できます。
次に、unshiftでメロンという文字列が配列の先頭に追加されます。
こちらも先頭に追加されていることがalertで確認できます。
最後に要素数が変更されたこともalertで確認できます。
pushは最後に要素が追加されるため、さほど考える必要がありませんが、unshiftは先頭に要素が追加されるため、配列宣言後からインデックスが変わることに注意が必要です。
配列の要素を削除する
配列から要素を削除します。
これにより配列数も変動します。
構文
配列名.pop();
配列名.shift();
pop・shiftともにメソッドで、カッコ内には削除する要素の記述は必要ありません。
なぜならpopは配列の最後、shiftは配列の先頭の要素を削除することが決まっているためです。
また、配列から削除された要素は、変数に代入して受け取ることができます。
コード例
//arrayDelete.js
const arr = ['メロン', 'りんご', 'みかん', 'いちご', 'ぶどう'];
const removedLast = arr.pop();
alert('要素数は' + arr.length + '\n配列の中身は' + arr + 'です');
const removedFirst = arr.shift();
alert('要素数は' + arr.length + '\n配列の中身は' + arr + 'です');
alert('削除した最後の要素は' + removedLast + '\n削除した最初の要素は' + removedFirst + 'です');
動作例
まず、removedLastにpopを使って、配列の最後の要素を削除すると同時に代入します。
削除されているかはalertで確認できます。
次に、removeFirstにshiftを使って、配列の最初の要素を削除すると同時に代入します。
こちらも削除されているかはalertで確認できます。
最後にpopで削除した要素と、shiftで削除した要素をalertで確認できます。
shiftもunshift同様、配列宣言後からインデックスが変わることに注意が必要です。
要素を検索・判定する
配列の中に、特定の値が含まれているかを調べたい場面はよくあります。
例えば、この商品はすでに登録されているか、条件に合うデータが存在するかなどです。
JavaScriptでは、配列の中身を探すためのメソッドと、その結果をもとに判定するためのメソッドが用意されています。
indexOf
配列の中から指定した値を検索し、その位置(インデックス)を調べます。
配列にその値が含まれているか、またどこにあるのかを確認したいときに使われます。
構文
配列名.indexOf('検索する値');
indexOfはメソッドで、カッコ内に検索したい値を1つ指定します。
配列の中にその値が存在する場合は、最初に見つかった位置のインデックス番号を返します。
存在しない場合は、-1を返します。
また、indexOfは完全一致で検索されます。
コード例
//arraySearch1.js
const arr = ['りんご', 'みかん', 'いちご'];
alert(arr.indexOf('りんご'));
alert(arr.indexOf('ぶどう'));
動作例
最初にarrの中からりんごを検索しています。
りんごは配列の0番目の要素なので、alertには0が表示されます。
次に、ぶどうを検索していますが、配列の中に存在しません。
そのため、alertには-1が表示されます。
indexOfは、値が存在するかどうかを調べるだけでなく、その値が配列のどの位置にあるかを確認したい場合に便利です。
なお、文字列の一部が一致していても検索結果にはなりません。
配列の中に同じ値が複数ある場合は、最初に見つかった位置のみが返されます。
includes
配列の中に指定した値が含まれているかを判定します。
結果はtrueまたはfalseの真偽値で返されます。
配列の中に完全に一致する値が存在するかどうかを、シンプルに確認したいときに使います。
構文
配列名.includes(検索する値, 開始位置);
includesはメソッドで、探したい値と検索を開始する位置を指定しますが、省略することがほとんどです。
開始位置を省略した場合は、配列の先頭から検索されます。
includesは配列の中に完全一致する値があるかどうかを判定するため、値の一部が一致してもtrueにはなりません。
なお、includesは配列専用のメソッドではなく、文字列にも使用できますが、文字列での使い方は文字列変換のページで解説します。
コード例
//arraySearch2.js
const arr = ['りんご', 'みかん', 'いちご'];
alert(arr.includes('みかん'));
alert(arr.includes('ぶどう'));
動作例
1つ目のalertでは、配列の中にみかんが含まれているためtrueが表示され、2つ目のalertでは、配列の中にぶどうが含まれていないためfalseが表示されます。
includesは配列の中身を1つずつ確認し、同じ値が見つかった時点でtrueを返します。
開始位置を省略しているのは、配列の中に完全一致する値があるかを調べる方法として扱っているためです。
find・some・every
配列の中から特定の条件に合う値を探したり、条件を満たしているかを判定したい場面は多くあります。
そのような場合、配列の各要素を順番に確認しながら処理を行う方法が用意されています。
これらは配列の中身を直接操作するのではなく、条件に合うかどうかをチェックするための仕組みです。
構文
配列名.find(条件);
配列名.some(条件);
配列名.every(条件);
find・some・everyはメソッドで、カッコ内には条件を指定します。
条件は関数として記述し、配列の各要素に対して順番に判定が行われます。
findは、条件に最初に一致した要素が見つかった時点で処理を終了し、その値を返します。
また、一致する要素が存在しない場合は、undefinedが返されます。
一方でsome・everyは条件に一致する要素が1つでも見つかった時点で処理は終了し、trueが返されます。
すべての要素が条件に一致しない場合は、falseが返されます。
コード例
//arraySearch3.js
const prices = [120, 300, 450, 800];
const findValue = prices.find(price => price < 400);
alert(findValue);
const someBool = prices.some(price => price < 400);
alert(someBool);
const everyBool = prices.every(price => price < 400);
alert(everyBool);
動作例
数値が入った配列pricesを用意し、同じ条件を使って3つのメソッドの動作を確認しています。
条件はいずれも「400未満かどうか」です。
まずfindは、条件に一致する要素を配列の先頭から順に調べます。
最初に条件を満たした値が見つかった時点で処理は終了し、その値が返されます。
この例では120が最初に400未満の値として見つかるため、alertには120が表示されます。
次にsomeは、条件に一致する要素が1つでも存在するかどうかを判定します。
配列の中に400未満の値が含まれているため、結果はtrueになります。
someは値そのものではなく、判定結果のみを返します。
最後にeveryは、すべての要素が条件を満たしているかどうかを判定します。
配列の中には800が含まれており、400未満ではない要素が存在するため、結果はfalseになります。
このように、同じ条件を使っていても、値を取得するのか、存在を判定するのか、すべてを確認するのかによって、返される結果が異なります。
なお、条件部分では、price => price < 400という少し見慣れない書き方が出てきます。
この=>はアロー関数と呼ばれる書き方です。
これは後のページで、詳しく解説しますが、find・some・everyを使う場合、この形で条件を書く必要があります。
配列の各要素は、priceの部分に1つずつ代入され、price < 400という条件で判定が行われます。
配列の検索や加工を行う際には、アロー関数と比較演算子は避けて通れない要素になります。
そのため、意味を理解できなくとも現時点ではこのような書き方になるという点だけ押さえておいてください。
配列の要素を並び変える
配列の中身を特定の条件で並び替えたい場面はよくあります。
数値を小さい順や大きい順に整えたり、データの順序を逆にしたりすることで、配列をより扱いやすい形にできます。
JavaScriptには、配列の要素の順番を変更するための仕組みが用意されています。
構文
配列名.sort(比較関数);
配列名.reverse();
sortとreverseはいずれもメソッドで、配列の並び順を変更します。
これらのメソッドは、配列そのものの順番を書き換えます。
なお、比較関数を省略すると文字列として比較して並び順を変更します。
コード例
//arraySort1.js
const arr = ['メロン', 'りんご', 'みかん', 'いちご', 'ぶどう'];
arr.sort();
alert(arr);
arr.reverse();
alert(arr);
動作例
まず、sortで配列の並び替えを行います。
並び変えた結果がalertで表示されます。
次に、reverseで配列の並び替えを逆順で行います。
こちらも並び変えた結果がalertで表示されます。
ところが、頭文字が持っている文字コードを基準にして並べ替えているため、五十音順には並びません。
そこで今回省略した比較関数が必要になります。
五十音順に並べる方法は後にソート機能を実装する際に説明します。
もう一つコードを見てもらいます。
コード例
//arraySort2.js
const arr = [1, 22, 133, 5, 2];
arr.sort();
alert(arr);
arr.reverse();
alert(arr);
動作例
文字列ではなく数値を配列に格納しました。
こちらも数字の大小で並べ替えが起こりません。
これは数値として配列で扱っているにもかかわらず、文字列として扱い並び替えが起こっているためです。
では、どうすれば数字順に並べ替えられるかというと、比較関数が必要になります。
なお、reverseはsortの有無にかかわらず、現在の配列を後ろから並べ替えを行っています。
そのため、sortで並べ替える前の状態ではなく、sort後の状態で並べ替えを行っています。
当然、sortを行わなかった場合は2・5・133・22・1の順に並べ替えが起こるだけとなります。
ここでは、並び替え自体はプログラムでできていると理解するだけでかまいません。
要素を加工・抽出する
配列の中身を条件に応じて加工したり、一部だけを取り出したりしたい場面は多くあります。
その際、元の配列を変更せず、新しい配列として結果を得たい場合もあります。
JavaScriptには、配列の各要素に処理を行って新しい配列を作ったり、必要な要素だけを抜き出した配列を作成する仕組みが用意されています。
ここでは、配列を加工・抽出する方法を確認していきます。
map
配列の各要素に同じ処理を行い、その結果を新しい配列として取得したい場面があります。
元の配列を変更せず、加工後のデータだけを使いたい場合です。
構文
配列名.map(処理);
mapはメソッドで、カッコ内には処理を指定します。
この処理は関数として記述され、配列の各要素に対して順番に実行されます。
mapは必ず新しい配列を返し、元の配列は変更されません。
コード例
//arrayMap.js
const prices = [100, 200, 300];
const result = prices.map(price => price * 2);
alert(result);
alert(prices);
動作例
数値が入った配列pricesを用意し、mapを使って各要素を加工しています。
処理では、配列の要素を2倍する計算を行っています。
mapは配列の先頭から順に要素を取り出し、priceの部分に1つずつ代入しながら、price * 2という処理を実行します。
その結果が新しい配列としてresultに代入されます。
1つ目のalertでは加工後の配列が表示され、2つ目のalertでは元の配列が変更されていないことが確認できます。
なお、mapは要素の数を変えないため、元の配列の要素数と同じになります。
filter
配列の中から、条件に合う要素だけを取り出したい場面があります。
すべての要素を加工するのではなく、必要なものだけを残したい場合です。
構文
配列名.filter(条件);
filterはメソッドで、カッコ内には条件を指定します。
この条件は関数として記述され、配列の各要素に対して順番に判定が行われます。
条件に一致した要素だけが、新しい配列に含まれます。
map同様、元の配列は変更されません。
コード例
//arrayFilter.js
const prices = [120, 300, 450, 800];
const result = prices.filter(price => price < 400);
alert(result);
alert(prices);
動作例
数値が入った配列pricesを用意し、filterを使って条件に400未満に合う要素を取り出しています。
filterは配列の先頭から順に要素を取り出し、priceの部分に1つずつ代入しながら、price < 400という条件で判定を行います。
条件に一致した要素だけが、新しい配列resultに追加されます。
この例では120、300が条件に一致するため、1つ目のalertにはそれらを含んだ配列が表示されます。
2つ目のalertでは、元の配列が変更されていないことが確認できます。
filterは要素を絞り込むため、元の配列と新しい配列では要素数が異なる場合があります。
slice
配列の中から、指定した範囲の要素だけを取り出したい場面があります。
条件で絞り込むのではなく、位置を指定して一部を抜き出したい場合です。
構文
配列名.slice(開始位置, 終了位置);
sliceはメソッドで、開始位置から終了位置の手前までの要素を取り出します。
元の配列は変更されません。
なお、sliceは配列専用のメソッドではなく、文字列にも使用できますが、文字列での使い方は文字列変換のページで解説します。
コード例
//arraySlice.js
const fruits = ['りんご', 'みかん', 'いちご', 'ぶどう', 'メロン'];
const result = fruits.slice(1, 4);
alert(result);
alert(fruits);
動作例
文字列が入った配列fruitsを用意し、sliceを使って一部の要素を取り出しています。
slice(1, 4)と指定することで、インデックス1からインデックス3までの要素が取り出されます。
この例では、みかん、いちご、ぶどうが新しい配列resultに含まれます。
1つ目のalertでは取り出された要素が表示され、2つ目のalertでは元の配列が変更されていないことが確認できます。
なお、sliceでは、終了位置を省略すると、指定した開始位置から配列の最後までの要素が取り出されます。
配列の要素を変換する
配列の要素をつなげて、1つの文字列として扱いたい場面があります。
配列のままではなく、表示用や送信用の文字列に変換したい場合です。
構文
配列名.join(区切り文字);
joinはメソッドで、カッコ内には要素同士をつなぐ区切り文字を指定します。
指定した区切り文字で要素を連結し、結果を文字列として返します。
元の配列は変更されません。
コード例
//arrayJoin.js
const fruits = ['りんご', 'みかん', 'いちご'];
const result = fruits.join('・');
alert(result);
動作例
文字列が入った配列fruitsを用意し、joinを使って1つの文字列に変換しています。
join('・')と指定することで、各要素の間に「・」を入れて結合しています。
この例では、りんご・みかん・いちごという1つの文字列が作成され、alertに表示されます。
なお、joinの戻り値は配列ではなく、文字列です。
そのため、joinの結果に対して配列のメソッドを使うことはできません。
また、区切り文字を省略した場合は、カンマで区切られた文字列が作成されます。
さらに、joinは配列全体を対象にするため、特定のインデックスだけを指定して結合することはできません。
一部の要素だけをつなげたい場合は、インデックスで取り出してから連結する必要があります。