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

Javascript: How to implement iterator over multidimensional array?

本文关键字:实现 迭代器 数组      更新时间:2023-09-26

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

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

Also not works.

但是如果我尝试这个:

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

很好。

这里有什么不同?如何使循环工作?

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

对于第二次元,您可以使用简单的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
    }
};

在这种情况下为什么需要循环呢?无论如何,你都在有效地使数组扁平化。你可以只增加索引和边界检查:

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>

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

大意

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