配列を回しながら削除したい場合
ときおり、「配列に何かの処理をかけてから、1つ1つ削除していく」ような処理が必要となるかもしれません。ただ、うまくやらないとハマります。
背景事情
Railsのフロントエンドの一部に、エレメントとしてRiotをはめ込んだようなアプリを作っていて、そしてTurbolinksでのページ遷移もかけていました。そうなると、ページ遷移の前にRiotをきちんと外しておく必要がありますので、以下のようなコードを書いていました。
幸い、マウント中のRiotタグの一覧はriot.util.vdom
に配列として入っています。ということで、
$(document).on('turbolinks:before-cache turbolinks:before-render', function(){
riot.util.vdom.forEach(function(item){
item.unmount(true);
});
});
のようにしていたのですが…調べてみると、一部のタグが残ってしまっていたのでした。
原因究明
Riot自体のソースコードまで当たって調べてみると、タグを.unmount
したのと同時にriot.util.vdom
からも.splice()
で削るようになっていました。そのため、
- 0番目のタグを
.unmount
-
.splice()
で、もともと1番目に入っていたものが0番目に移る -
forEach
が1番目に進んでしまう - もと奇数番目だったものは、飛ばされて残ってしまう
という、単純な理屈でした。なお、JavaScriptの.forEach
も、中身はこのように添字を回すのが基本です。
対策法
対策としては、いくつか考えられます。
後ろから回す
後ろから回していけば、順々に削除していっても番号がずれることはないので、そのような問題は生じません。Rubyの配列にはreverse_each
メソッドがありますが、JavaScriptでは添字をfor
で回していく他なさそうです。
配列をコピーする
操作対象となる配列とは別に、参照用に配列をコピーしておいて、そちらから操作する、という方法もあります。ただし、コピーのコストはかかります。
破壊的操作と要素の取り出しを一気に済ませる
配列から.pop()
や.unshift()
で要素を取り出しつつ削っていくようにできれば、「ループの位置」という概念も関係なくなりますし、全部終われば配列は自然と空になっています。
Author And Source
この問題について(配列を回しながら削除したい場合), 我々は、より多くの情報をここで見つけました https://qiita.com/jkr_2255/items/be7466c38855ee94ff88著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .