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

时间:2015-10-06 11:32:21

标签: javascript arrays multidimensional-array iterator closures

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

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

也行不通。

但如果我试试这个:

String dealerID
String dealerIDConstraint
String carID
String tyreID

static constraints = {
    dealerID           nullable: true
    dealerIDConstraint blank: false
    carID              blank: false, unique: ['tyreID','dealerIDConstraint']
    tyreID             blank: false
}

// This will cover updates from web pages.
def beforeValidate() {
    updateDealerIDConstraint()
}

// This will cover direct access.
void setDealerID(String dealerId) {
    this.dealerId = dealerId

    updateDealerIDConstraint()
}

/**
 * Ensure the validation only field is up to date.
 */
private void updateDealerIDConstraint() {
    dealerIDConstraint = dealerID ?: tyreID + "-" + carID
}

工作正常。

这有什么区别?如何进行循环工作?

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

3 个答案:

答案 0 :(得分: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
    }
};

答案 1 :(得分:1)

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

一般理念

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

答案 2 :(得分:1)

在这种情况下,为什么你需要一个循环呢?无论如何,你实际上是在扁平化阵列。您可以只增加索引以及边界检查:

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>