ゼロからはじめるプログラミング講座の第二十九回です。前回に続いて今回は配列の要素の削除方法を解説します。
メソッドを使って配列の要素を削除しよう。
要素を追加するときにはpush,unshift,spliceを使いました。
まずは.pop()のメソッドです。popは配列の末尾の要素を削除します。
var arr = ["a","b","c"]
arr.pop()
console.log(arr.length) // 要素数
console.log(arr[arr.length-1]) // length-1で現在の末尾を指定
b
コンソールで要素数を表示すると2になっています。末尾は”b”です。
もしpopを使わず空文字で書き換えた場合どうなるかを見てみましょう。
var arr = ["a","b","c"]
arr[2] = ""
console.log(arr.length)
console.log(arr[arr.length-1])
このように配列の要素数は3のままです。コンソールで最後尾を参照したところ空文字が表示されました。最後尾を削除するにはpopを使いましょう。
次は.shift()のメソッドです。先頭に追加するunshiftと似ているshiftは先頭を削除するメソッドです。
var arr = ["a","b","c"]
arr.shift()
console.log(arr.length)
console.log(arr[0])
b
要素数も2になっていて先頭も”a”を消して間を詰めて”b”が入っています。
最後に.splice()のメソッドです。spliceは要素を指定した場所に追加する方法として前回学びましたね、spliceは要素を削除することもできるのです。
var arr = ["a","b","c","d","e"]
arr.splice(2,1) // arr[2]から1つ要素を削除する。
for(var i=0; i<arr.length; i++){
console.log(arr[i])
}
b
d
e
spliceの引数に渡すものをもう一度確認してみましょう。
- 第一引数:追加する区画番号
- 第二引数:第一引数の後ろの要素を削除する個数
- 第三引数:追加する要素
arr.splice(2,1)
第一引数:この場合追加する場所はarr[2]です。
第二引数:追加する場合は0に固定していましたが1なら後ろの要素を1つ削除します。
第三引数:無いので何も追加しません。何も追加しないので第一引数に指定した場所から削除されていきます。
forループで要素の追加、削除をする場合は注意しよう。
forループを使って配列に要素を追加したり削除するときは少し注意が必要です。
フリーズが起こったり、思った結果が得られないことがあります。
まず要素を追加する場合は無限ループによりフリーズすることがあります。それを確認していきましょう。このコードはフリーズするので実行する場合は注意してください。
var arr = ["a","b","a","b","a"]
for(var i=0; i<arr.length; i++){
if(arr[i] == "b"){
arr.push("b")
}
}
何故このコードが無限ループになるか、問題はfor文の条件にあります。{}内処理のように”b”があったら末尾に”b”を追加するのように同じものを追加するという処理自体は問題ではありません。
i<arr.length この部分で条件を確認するときに毎回配列の要素数を確認しているのが問題です。pushで配列を追加したら要素数は増えていってしまいます。
この要素数をfor文開始時の要素数に固定しておけばpushで要素を追加しても無限ループになることはありません。改良したコードがこちらです。
var arr = ["a","b","a","b","a"]
var r = arr.length // 要素数を変数rに入れておく。
for(var i=0; i<r; i++){ // 条件はi<rなので増えることはない
if(arr[i] == "b"){
arr.push("b")
}
}
for(var i=0; i<arr.length; i++){
console.log(arr[i])
}
b
a
b
a
b
b
これで期待通りの結果が得られました。このコードも一部書き換えてクールにするテクニックがあるので紹介しておきます。
var r = arr.length;
for(var i=0; i<r; i++){
↓一行減らすことができます。
for(var i=0, r=arr.length; i<r; i++){
for文の最初の変数の初期化時に変数rも初期化するのです。
var i=0, r=arr.length ←この書き方は
var i=0
var r = arr.length と二行に分けて書くのと同じです。
次にforループの中で要素を削除する場合を見ていきます。
要素を削除する場合は無限ループになることはありませんが期待した結果を得られないことがあります。コードを実行して確認していきましょう。
var arr = ["a","b","b","b","a"]
for(var i=0; i<arr.length; i++){
if(arr[i] == "b"){
arr.splice(i,1)
}
}
for(var i=0; i<arr.length; i++){
console.log(arr[i])
}
b
a
ループで配列の中にある”b”をspliceで削除していく処理ですが、コンソールには”b”が表示され配列に”b”がまだ残っています。これはどうなっているのでしょうか?
ループ1回目はi=0でarr[0]は”a”なので何事もなくi++をして次のループへ行きます。
ループ2回目はi=1です。
arr.splice(i,1)で”b”を1つ削除すると配列arrは[“a”,”b”,”b”,”a”]となっています。
そしてi++の後に次のループに入ります。
ループ3回目はi=2です。arr[i]はarr[2]で[“a”,”b”,“b”,”a”]を参照します。
arr.splice(i,1)はarr.splice(2,1)となり[“a”,”b”,“b”,”a”]を削除して[“a”,”b”,”a”]になります。
i++されてi=3となり次の条件 i<arr.length はfalse偽となりループを抜けます。
このようにspliceで削除したら間は詰められるのでforループでは要素をスキップしてしまうことがあります。これを防ぐにはコードを改良する必要があります。
var arr = ["a","b","b","b","a"]
for(var i=0; i<arr.length; i++){
if(arr[i] == "b"){
arr.splice(i,1)
i-- // iを減らすことでもう一度同じ位置を確認できる。
}
}
for(var i=0; i<arr.length; i++){
console.log(arr[i])
}
a
こんどは期待通りの結果が得られました。削除して間を詰めた分だけiを減らしてやればよいのです。
ループで要素を追加するときはループがきちんと終了するように条件を作りましょう。
ループで要素を削除するときはスキップが起こらないように要素を削除した数だけiを減らしましょう。
お疲れ様でした。配列はループで処理することが多々あるので狙った通りの結果が得られない場合はこの解説をもう一度読み直しましょう。次回は多次元配列を解説します。
次も頑張って記事を作るのでチャレンジしてください!
JavaScript #1/#2/#3/#4/#5/#6/#7/#8/#9/#10/#11/#12/#13/#14/#15/#16/#17/#18/#19/#20
∩∩
(´・ω・)
_| ⊃/(___
/ └-(____/
 ̄ ̄ ̄ ̄ ̄ ̄ ̄
来たら起こして。
⊂⌒/ヽ-、__
/⊂_/____ /
 ̄ ̄ ̄ ̄ ̄ ̄ ̄