kkana's blog

新米コーダーの忘れそうなことメモ

大量のオブジェクトを処理するときに考えた事(1)(イテレーターパターンについて)

追記:
後日 この記事を書いた時点でイテレーターパターンと連結リストを混同していた事がわかりました・・・
最初の様子を残しておきたいのでこのままにしておきます 笑


tuitui.hatenablog.com

このコードを書いているときにイテレーターパターンというものがわかった(気がする)!
今回のコードは粒子系で、どうしても動かすオブジェクトの量が増えてしまう・・・ それを毎回for文で回すときにちょっと工夫しました。

イテレータパターンとは

itpro.nikkeibp.co.jp

このサイトがわかりやすい。 思い返してみたら前にもBox2dWebを使ってみる(2) - kkana's blogここで Box2Dワールドから物体の座標を取り出すときに使っていました。

配列みたいに順番にまとまってるものに対してindexを振らなくても良いのが利点。
データの構造を知らなくても個々の要素にアクセスできればよい、ので提供する情報も少なくて大丈夫そう。
hasNext()でまだ次の要素があればtrueを、なければfalseを返すメソッドを用意すると、
そのデータ個々に処理をかけたい気に、次があるならまだ続ける、なければ終了、とwhile文を使ってかける。
要素が増えてもindexをふり直さなくても良い!素晴らしい〜。

JavaScriptパターン ―優れたアプリケーションのための作法

JavaScriptパターン ―優れたアプリケーションのための作法

この本でいうと、7.3に出てきます。

また、ここのサイトも参考にしました。

gihyo.jp

教本(processing)ではどうしているのか

ArrayList<Particle> particles;
 
void setup() {
  size(640,360);
  particles = new ArrayList<Particle>();
}
 
void draw() {
  background(255);
A new Particle object is added to the ArrayList every cycle through draw().
  particles.add(new Particle(new PVector(width/2,50)));
 
  for (int i = 0; i < particles.size(); i++) {
    Particle p = particles.get(i);
    p.run();
  }
}

ArrayListというものがあるんですね・・。いいなぁ。
javascriptにもあるのかな、と思って探したけれどわかりませんでした。

実際書いたコード

ES6での書き方は(もうちょっと書きやすい方法があるかもしれませんが・・・)とりあえずcodepenに書いたので 、ES5の書き方をメモしておきます。

今回必要かな、と思って書いた機能は以下です。

  • リストに要素を追加する
  • 現在ポインタのさしている要素を返す
  • 次の要素があるかどうか返す
  • 次の要素を返す
  • ポインタをはじめに戻す
//連結リストのクラス
  var LinkedList = function(){
      //長さ
      this.length = 0;
      //ポインタの位置
      this.index = 0;
      //データ
      this.data = [];
  }
    //挿入されたものを追加
  LinkedList.prototype = {
    push : function(elm){
      this.data.push(elm);
      this.length++;
    },
    //現在の要素を返す
    current : function(){
      return this.data[this.index];
    },
    //次があるか?
    hasNext : function(){
      if(this.index < this.length){
        return true;
      }
      else{
        return false;
      }
    },
    //次の要素を返す
    next : function(){
      if(!this.hasNext()){
        return false;
      }
      else{
        this.index++;
        return this.data[this.index];
      }
    },
    //ポインタを先頭に戻す
    rewind : function(){
      this.index = 0;
    }
  }

使うときは、こういう感じで

var list = new LinkedList();
for (var i = 0; i < 10; i++) {
  var p = i;
  list.push(p);
}

while (list.hasNext()) {
  console.log(list.current());
  list.next();
}

list.push('p');
list.rewind();

while (list.hasNext()) {
  console.log(list.current());
  list.next();
}

教本の読んでいる章がついに複雑系に入ってきたので、たぶんこれからも出番があると思われる。
またいつものように書き直しながら使っていきたいな。

そして、イテレータで回している途中に、またイテレータで回したいとき (個々のオブジェクトを操作してるときに、その操作の中でまた個々のオブジェクトを操作するときとか・・) にポインタをみうしなって結局for文で書く事に・・。
なにかうまいやり方はないものか。

ES6にイテレーターパターンが最初からあるかも

と、ここまで書いて気がついたんですが ES6にはイテレーターパターン的なものが最初から用意されてるみたい。

developer.mozilla.org

developer.mozilla.org

js-next.hatenablog.com

qiita.com

十六章第二回 イテレータ — JavaScript初級者から中級者になろう — uhyohyo.net

全然わからなかったので、また後日しっかり読もう・・・。