LoginSignup
5
1

More than 3 years have passed since last update.

Javascriptで自前のコンテナクラスにイテレータを実装する

Last updated at Posted at 2019-06-21

自前でコンテナを作成してvueのv-forで表示する機会があって、情報を探すのに苦労したのでメモ残しときます。
実装は管理ノードつきの双方向循環リストです。(横着な実装なので正確にはコンテナではない気がします・・・。)
方法1はnext()を持ったオブジェクトなら何でも良いのですが、その一例としてここではジェネレータを返却しています。

list.js
class List {
    constructor(data=null) {
        this.prev = this;
        this.next = this;
        this.data = data;
    }

    insert_next(e) {
        if(this == e) return;
        e.prev.next = e.next;
        e.next.prev = e.prev;
        e.prev = this;
        e.next = this.next;
        this.next.prev = e;
        this.next = e;
    }

    insert_prev(e) {
        this.prev.insert_next(e);
    }

    pop() {
        this.prev.next = this.next;
        this.next.prev = this.prev;
        this.next = this;
        this.prev = this;
    }

    is_empty() {
        return this.next == this;
    }

    // 方法1 : for(let i of list)のような使い方をしたい場合
    // 定義したジェネレータをインスタンス化して返却
    [Symbol.iterator]() {
        return  function *(){
            for(let l = this.next; l != this; l = l.next) {
                yield l.data;
            }
        }.bind(this)();
    }

    // 方法2 : 明示的なイテレータ
    // ジェネレータをそのまま定義
    *iterator() {
        for(let l = this.next; l != this; l = l.next) {
            yield l.data;
        }
    }
}

// 以下サンプルコード
let l = new List(); // 管理ノードの作成

console.log('初期化');
for(let i = 0; i < 10; ++i) {
    l.insert_prev(new List(i));
}
for(let i of l) { // 方法1のイテレータ
    console.log(i);
}

console.log('管理ノードの移動');
l.next.next.next.insert_next(l);
for(let i of l.iterator()) { // 方法2のイテレータ
    console.log(i);
}

console.log('管理ノード以外の全削除');
while(!l.is_empty()) {
    l.next.pop();
}
for(let i of l) {
    console.log(i);
}
node.jsで実行した結果
初期化
0
1
2
3
4
5
6
7
8
9
管理ノードの移動
3
4
5
6
7
8
9
0
1
2
管理ノード意外の全削除
5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1