36 javascript circular-buffer data-structures
有人已经在JavaScript中实现了循环缓冲区吗?没有指针你会怎么做?
bob*_*nce 31
奇怪的共同发生,我今天刚刚写了一篇!我不知道你的要求究竟是什么,但这可能是有用的.
它呈现的界面就像一个无限长度的数组,但"忘记"旧项:
// Circular buffer storage. Externally-apparent 'length' increases indefinitely
// while any items with indexes below length-n will be forgotten (undefined
// will be returned if you try to get them, trying to set is an exception).
// n represents the initial length of the array, not a maximum
function CircularBuffer(n) {
this._array= new Array(n);
this.length= 0;
}
CircularBuffer.prototype.toString= function() {
return '[object CircularBuffer('+this._array.length+') length '+this.length+']';
};
CircularBuffer.prototype.get= function(i) {
if (i<0 || i<this.length-this._array.length)
return undefined;
return this._array[i%this._array.length];
};
CircularBuffer.prototype.set= function(i, v) {
if (i<0 || i<this.length-this._array.length)
throw CircularBuffer.IndexError;
while (i>this.length) {
this._array[this.length%this._array.length]= undefined;
this.length++;
}
this._array[i%this._array.length]= v;
if (i==this.length)
this.length++;
};
CircularBuffer.IndexError= {};
Run Code Online (Sandbox Code Playgroud)
Tor*_*ker 20
var createRingBuffer = function(length){
var pointer = 0, buffer = [];
return {
get : function(key){return buffer[key];},
push : function(item){
buffer[pointer] = item;
pointer = (length + pointer +1) % length;
}
};
};
Run Code Online (Sandbox Code Playgroud)
更新:如果你只用数字填充缓冲区,这里有一些衬里插件:
min : function(){return Math.min.apply(Math, buffer);},
sum : function(){return buffer.reduce(function(a, b){ return a + b; }, 0);},
Run Code Online (Sandbox Code Playgroud)
像许多其他人一样,我喜欢noiv的解决方案,但我想要一个更好的API:
var createRingBuffer = function(length){
/* https://stackoverflow.com/a/4774081 */
var pointer = 0, buffer = [];
return {
get : function(key){
if (key < 0){
return buffer[pointer+key];
} else if (key === false){
return buffer[pointer - 1];
} else{
return buffer[key];
}
},
push : function(item){
buffer[pointer] = item;
pointer = (pointer + 1) % length;
return item;
},
prev : function(){
var tmp_pointer = (pointer - 1) % length;
if (buffer[tmp_pointer]){
pointer = tmp_pointer;
return buffer[pointer];
}
},
next : function(){
if (buffer[pointer]){
pointer = (pointer + 1) % length;
return buffer[pointer];
}
}
};
};
Run Code Online (Sandbox Code Playgroud)
原始改进:
get 支持默认参数(返回最后一项推送到缓冲区)get 支持负索引(从右计算)prev 将缓冲区移回一个并返回那里的内容(如弹出而不删除)next 撤消prev(向前移动缓冲区并返回它)我用它来存储一个命令历史记录,然后我可以使用它prev和next方法在应用程序中翻转,当它们无处可去时很好地返回undefined.
差不多 10 年后,一个使用 JavaScript ES6 的答案:
class CircularBuffer {
constructor(bufferLength) {
this.buffer = [];
this.pointer = 0;
this.bufferLength = bufferLength;
}
push(element) {
if(this.buffer.length === this.bufferLength) {
this.buffer[this.pointer] = element;
} else {
this.buffer.push(element);
}
this.pointer = (this.pointer + 1) % this.bufferLength;
}
get(i) {
return this.buffer[i];
}
//Gets the ith element before last one
getLast(i) {
return this.buffer[this.pointer+this.bufferLength-1-i];
}
}
//To use it:
let circularBuffer = new CircularBuffer(3);
circularBuffer.push('a');
circularBuffer.push('b');
circularBuffer.push('c');
// should print a,b,c
console.log(`0 element: ${circularBuffer.get(0)}; 1 element: ${circularBuffer.get(1)}; 2 element: ${circularBuffer.get(2)};`);
console.log('Last element: '+circularBuffer.getLast(0)); // should print 'c'
circularBuffer.push('d');
// should print d,b,c
console.log(`0 element: ${circularBuffer.get(0)}; 1 element: ${circularBuffer.get(1)}; 2 element: ${circularBuffer.get(2)};`);Run Code Online (Sandbox Code Playgroud)