自前でコンテナを作成して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
管理ノード意外の全削除