【问题标题】:Javascript: How to implement iterator over multidimensional array?Javascript:如何在多维数组上实现迭代器?
【发布时间】:2015-10-06 11:32:20
【问题描述】:

我有 2 个暗淡的数组,看起来像这样:

var a = [[1,2,3],[4,5,6],[7,8,9]];

我想写一个迭代器,每次调用它都会返回一个值。

iterator(); //returns 1
iterator(); //returns 2
iterator(); //returns 3

我试过这样的方法:

function iterator() {
    var a = [[1,2,3],[4,5,6],[7,8,9]];
    var i, j;
    return function() {
        for (var i = 0; i < a.length; i++) {
            var b = a[i];
            for (var j = 0; j < b.length; j++) {
                return a[i][j];
            }
        }
    }
};
var a = iterator();
a(); //1
a(); //1
a(); //1

它总是返回我第一个元素。

我可以试试这个:

function iterator() {
    var a = [[1,2,3],[4,5,6],[7,8,9]];
    var i = 0, j = 0;
    return function() {
        for (; i < a.length; i++) {
            var b = a[i];
            for (; j < b.length; j++) {
                return a[i][j];
            }
        }
    }
};

也不行。

但如果我试试这个:

function test() {
    var a = [1,2,3,4,5], i = 0;
    return function() {
        while (i < a.length) {
            return a[i++];
        }
    }
}
var a = test();
a(); //1
a(); //2
a(); //3

它工作正常。

这里有什么区别?如何使 for 循环工作?

对我来说另一个明显的问题是界限。到达数组边界时应该如何停止?

【问题讨论】:

  • 每次调用函数时都使用 for 循环初始化 i=0 , j=0..
  • @Haketo 进行了编辑,检查我的第二次尝试迭代器。也不行。
  • 因为你从不增加i和j,所以它会在之前执行return语句
  • 为什么不直接折叠数组?
  • @epascarello 我用它作为二维结构来填充网格。

标签: javascript arrays multidimensional-array iterator closures


【解决方案1】:

您可以使用简单的if 来测试j 的边界,而不是对第二维使用内部for 循环

function iterator() {
    var a = [[1,2,3],[4,5,6],[7,8,9]];
    var i = 0, j = 0;
    return function() {
        for (; i < a.length; i++) {
            var b = a[i];
            if (j < b.length){
                return a[i][j++];
            }
            j = 0;
        }
        return undefined; // reached when there is no value left
    }
};

【讨论】:

  • 其实循环是没有必要的。你可以只返回 a[i][j] 或 undefined。
  • @AdrianMaire for-loop 只是为了简化ii 增量的边界检查(保存一行。)我添加了return undefined 因为OP 可能想要返回一些东西除了undefined
【解决方案2】:

为什么在这种情况下你需要一个循环。无论如何,您都在有效地展平阵列。您可以只增加索引以及边界检查:

function iterator() {
    var a = [[1,2,3],[4,5,6],[7,8,9]], i = 0, j = 0;
    return function() {
        if (j >= a[i].length) { j = 0; i++; }
        if (i >= a.length) { j = 0; i = 0; }
        snippet.log( a[i][j++] );
    }
};
var x = iterator();
x(); x(); x(); x(); x(); x(); x(); x(); x(); x(); 
x(); x(); x(); x(); x(); x(); x(); x(); x(); x();
&lt;script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"&gt;&lt;/script&gt;

【讨论】:

    【解决方案3】:

    扩展标准功能通常不是一个好主意,但对于一个教学示例,我会例外。对于实际使用,我建议实现您自己的类。

    总体思路

    Array.prototype.beginIterator = function()
    {
        var counter = 0;
        return function()
            { 
                if (counter<=this.length) return this[counter++]; 
                else return undefined;
            };
    }
    

    然后你可以像下面这样迭代:

    var a = [3,1,4,1,5];
    var it = a.beginIterator();
    for (var i=it(); i!=undefined; i=it())
    {
        alert(i);
    }
    

    目前这仅适用于一维数组,但它可以与任何逻辑一起应用于其他数组或对象。

    多维(Any)解决方案:

    以下迭代器允许任意组合的任意维度数组:

    Array.prototype.beginIterator = function()
    {
        var counter = 0;
        var iterators = null;
    
        return function()
            { 
                val = undefined;
                if (iterators!=null)
                {
                    val = iterators();
                    if (val!==undefined) return val;
                    else
                    {
                        iterators = null;
                        counter++;
                    }
                }
    
                while (counter <=this.length)
                {
                    if (!(this[counter] instanceof Array)) return this[counter++];
                    else
                    {
                        iterators = this[counter++].beginIterator();
                        val = iterators();
                        if (val!==undefined) return val;
                    }
                }
                return undefiend;
            };
    }
    

    使用示例:

    var a = [3,[3,5,7],4,[1,[2,5,8]],5];
    var it = a.beginIterator();
    for (var i=it(); i!=undefined; i=it())
    {
        alert(i);
    }
    

    【讨论】:

      猜你喜欢
      • 2019-08-21
      • 2023-03-08
      • 2014-05-17
      • 1970-01-01
      • 1970-01-01
      • 2018-03-16
      • 1970-01-01
      相关资源
      最近更新 更多