【问题标题】:Attempt at Circular Buffer - Javascript尝试循环缓冲区 - Javascript
【发布时间】:2013-11-21 11:18:34
【问题描述】:

对!这是我对循环缓冲区的尝试(用于图形程序,使用 canvas 元素)。还没有开始测试它。

问题是 - 谁能看出我的逻辑有任何缺陷?还是瓶颈?

/**
*   A circular buffer class.
*   @To add value -> bufferObject.addValue(xValue, yValue);
*   @To get the First-in value use -> bufferObject.getValue(0);
*   @To get the Last-in value use -> bufferObject.getValue(bufferObject.length);
**/

var circularBuffer = function (bufferSize) {

    this.bufferSize = bufferSize;
    this.buffer = new Array(this.bufferSize); // After testing on jPerf -> 2 x 1D array seems fastest solution.

    this.end = 0;
    this.start = 0;

    // Adds values to array in circular.
    this.addValue = function(xValue, yValue) {
        this.buffer[this.end] = {x : xValue, y: yValue};
        if (this.end != this.bufferSize) this.end++;
        else this.end = 0;
        if(this.end == this.start) this.start ++;
    };

    // Returns a value from the buffer
    this.getValue = function(index) {

        var i = index+this.start;

        if(i >= this.bufferSize) i -= this.bufferSize; //Check here.

        return this.buffer[i]
    };

    // Returns the length of the buffer
    this.getLength = function() {
        if(this.start > this.end || this.start == this.bufferSize) {
            return this.xBuffer.length;
        } else {
            return this.end - this.start;
        }
    };

    // Returns true if the buffer has been initialized.
    this.isInitialized = function() {
        if(this.end != this.start) return true;
        else return false;
    };
}

请随意重用此代码。

更新了两次(并经过测试!)。

【问题讨论】:

  • 是的,在 this.getValue 中计算缓冲区的索引过于频繁。 x 和 y 对一起运行,所以你应该能够得到 point = this.buffer[index]; y = point.y x=point.x 或类似的。
  • 感谢您的快速回复!不确定我是否完全理解它。喝完这杯咖啡可能对我更有意义。
  • 知道了。你的意思是添加一个变量... [convertIndex = index+this.start;] 然后重用它。如果是这样,完成。谢谢!
  • 我的性感重写 -> [ this.getValue = function(index) { var i = index+this.start; if(i >= this.bufferSize) i -= this.bufferSize;返回 { x : this.xBuffer[i], y : this.yBuffer[i], }; };]
  • 这是一个开始:-),但我认为您也可以将 xBuffer 和 yBuffer 合并到简单的缓冲区中。最好在进行更改时编辑您的原始问题,并简单地记下您已对其进行了更新

标签: circular-buffer


【解决方案1】:

更新:找到另一个实现Circular buffer in JavaScript

将类变量设为私有,更正了旧的 xBuffer 引用。今晚将进行更多编辑。

/**
*   A circular buffer class.
*   @To add value -> bufferObject.addValue(xValue, yValue);
*   @To get the First-in value use -> bufferObject.getValue(0);
*   @To get the Last-in value use -> bufferObject.getValue(bufferObject.length);
**/

var circularBuffer = function (buffer_size) {

    var bufferSize = buffer_size;
    var buffer = new Array(bufferSize); // After testing on jPerf -> 2 x 1D array seems fastest solution.

    var end = 0;
    var start = 0;

    // Adds values to array in circular.
    this.addValue = function(xValue, yValue) {
        buffer[end] = {x : xValue, y: yValue};
        if (end != bufferSize) end++;
        else end = 0;
        if(end == start) start++;
    };

    // Returns a value from the buffer
    this.getValue = function(index) {

        var i = index+start;

        if(i >= bufferSize) i -= bufferSize; //Check here.

        return buffer[i];
    };

    // Returns the length of the buffer
    this.getLength = function() {
        if(start > end || start == bufferSize) {
            return buffer.length;
        } else {
            return end - start;
        }
    };

    // Returns true if the buffer has been initialized.
    this.isInitialized = function() {
        return (end != start) ? true : false;
    };
}

【讨论】:

  • 你是个了不起的家伙。谢谢。不要再担心了(除非是为了个人成就:D)。看起来很漂亮!
  • 每当我浏览 Stackoverflow 的其他问题时,我倾向于完善我的答案 :-)
  • 建议您查看链接 - 此版本可能有效,但早期的解决方案可能更优雅。特别是,推送和弹出可能会消除复杂索引计算的需要
【解决方案2】:

我在上面实现了 Vogomatix 的代码,但遇到了一些错误。代码会注销缓冲区的末尾,自动扩展缓冲区大小,并将 addValue 函数绑定到特定类型。我已经调整了代码以适用于任何对象类型,添加了一些私有子例程来简化,并添加了一个函数来将内容转储到字符串中,并带有一个可选的分隔符。还使用了命名空间。

缺少的是 removeValue(),但它只是检查计数是否大于零,然后调用 _pop()。

这样做是因为我需要一个滚动的、滚动的入站消息文本缓冲区,它不会无限增长。我将对象与 textarea 一起使用,因此我得到了类似控制台窗口的行为,即不会无限期地占用内存的滚动文本框。

为了方便起见,这已经过测试,因为我正在快速编码,因此在此处发布,希望 OverFlow 的同胞使用并退火代码。

///////////////////////////////////////////////////////////////////////////////
// STYLE DECLARATION
// Use double quotes in JavaScript


///////////////////////////////////////////////////////////////////////////////
// Global Namespace for this application
//

var nz = nz || {};
nz.cbuffer = new Object();


///////////////////////////////////////////////////////////////////////////////
// CIRCULAR BUFFER
//

// CREDIT: 
// Based on...
// Vogomatix http://stackoverflow.com/questions/20119513/attempt-at-circular-buffer-javascript
// But re-written after finding some undocumented features...
/**
*   A circular buffer class, storing any type of Javascript object.
*   To add value -> bufferObject.addValue(obj);
*   To get the First-in value use -> bufferObject.getValue(0);
*   To get the Last-in value use -> bufferObject.getValue(bufferObject.length);
*   To dump to string use -> bufferObject.streamToString(sOptionalDelimiter); // Defaults to "\r\n"
**/

nz.cbuffer.circularBuffer = function (buffer_size) {

    var bufferSize = buffer_size > 0 ? buffer_size : 1; // At worst, make an array of size 1
    var buffer = new Array(bufferSize);

    var end = 0; // Index of last element.
    var start = 0; // Index of first element.
    var count = 0; // Count of elements

    // 'Private' function to push object onto buffer.
    this._push = function (obj) {
        buffer[end] = obj; // Write
        end++; // Advance        
        if (end == bufferSize) {
            end = 0; // Wrap if illegal
        }
        count++;
    }

    // 'Private' function to pop object from buffer. 
    this._pop = function () {
        var obj = buffer[start];
        start++;
        if (start == bufferSize) {
            start = 0; // Wrap
        }
        count--;
        return obj;
    }

    // Adds values to buffer.
    this.addValue = function (obj) {
        if (count < bufferSize) {
            // Just push
            this._push(obj);
        }
        else {
            // Pop, then push
            this._pop();
            this._push(obj);
        }
    }

    // Returns a value from the buffer.  Index is relative to current notional start.
    this.getValue = function (index) {

        if (index >= count || index < 0) return; // Catch attempt to access illegal index

        var i = index + start;

        if (i >= bufferSize) {
            i -= bufferSize;
        }

        return buffer[i];
    }

    // Returns the length of the buffer.
    this.getLength = function () {
        return count;
    }

    // Returns all items as strings, separated by optional delimiter.
    this.streamToString = function (delim) {

        delim = (typeof delim === "undefined") ? "\r\n" : delim; // Default syntax; Default to CRLF

        var strReturn = "";

        var once = 0;
        var index = 0;
        var read = index + start;
        for (; index < count; ++index) {
            if (once == 1) strReturn += delim.toString();
            strReturn += buffer[read].toString();
            read++;
            if (read >= bufferSize) read = 0;
            once = 1;
        }

        return strReturn;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-25
    • 2019-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多