Javascript: 如何在多维数组上实现迭代器?

Javascript: How to implement iterator over multidimensional array?

我有 2 个 dim 数组,看起来像这样:

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

我想写一个迭代器,当它被调用时,它会return一个值。

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

它总是 return 是我的第一个元素。

我可以试试这个:

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 循环工作?

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

您可以使用简单的 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
    }
};

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

总体思路

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);
}

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

多维(任意)解:

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

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);
}

为什么在这种情况下你需要一个循环。无论如何,您实际上是在展平数组。您可以在进行边界检查的同时增加索引:

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();
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>