【问题标题】:How to create a counting generator/iterator cascade in JavaScript?如何在 JavaScript 中创建计数生成器/迭代器级联?
【发布时间】:2014-10-09 07:59:03
【问题描述】:

较新版本的 JavaScript 允许将 generators/iteratorsyield 关键字结合使用。


我的问题背景

考虑以下生成器,它“生成”从 0 到 9 的数字(数字):

// generator (produces numbers from 0 to 9, then stops)
function *zcounter() {
  var i = 0;
  while (i<=9) {
    yield i;
    i++;
  }
}

现在我想用它来替换以下函数,它使用了 3 个嵌套的 for 循环:

// e.g.: var iArray=[0,0,0];
function IterateCascade1(iArray) {
    var iterations=0;
    for (var x=0; x<=9; x++) {
        iArray[0]=x;
        for (var y=0; y<=9; y++) {
            iArray[1]=y;
            for (var z=0; z<=9; z++) {
                iArray[2]=z;
                logArray(iArray);
                iterations++;
            }
        }
    }
    return iterations;
}

问题

如果你像上面那样调用函数

console.log("Iterations: "+IterateCascade1([0,0,0]));

然后它会从000到999计数1000次,这正是我想要的。

缺点是只能使用3个元素的数组,不能传递更多元素的数组。


为了使用生成器zcounter()解决它,我尝试了以下方法:

// e.g.: var iArray=[0,0,0];
function IterateCascade2(iArray) {
    var iterations=0;
    // generate 3 iterators
    var gArray = [];
    for(var i=0; i<iArray.length; i++) {    
        var g=zcounter();
        gArray[i]=g;
    }
    // loop through
    for(var a in gArray) {
        //console.log("a:"+a);
        var g=gArray[a];
        var gnext=g.next();
        while (!gnext.done)
        {
            iArray[a]=gnext.value;
            logArray(iArray);
            gnext=g.next();
            iterations++;
        }
    }
    return iterations;
}

如果你像上面那样调用函数

console.log("Iterations: "+IterateCascade2([0,0,0]));

那么它只会计数30次,它不会像IterateCascade1那样遍历所有1000个数字。

此外,如果您传递更大的数组,例如

console.log("Iterations: "+IterateCascade2([0,0,0,0]));

然后它将“计数”从 0 到 9 的每个数字,但不会遍历所有 10000 个组合。


问题

我知道不知何故缺少递归。

  • 如何修改 IterateCascade2 以使其正确运行(循环遍历所有组合,您可以传递任意大小的整数数组)?

注意:

为了显示组合,我使用了

function logArray(x) {
    var result="";
    for(var i=0; i<x.length; i++) { result += x[i].toString(); }
    console.log(result);
}

在上面的例子中。您可以使用 3 种浏览器中任何一种的开发者工具或 JSShell 来运行代码。

【问题讨论】:

    标签: javascript arrays iterator generator yield


    【解决方案1】:

    这是一个递归解决方案

    function iterareIndex(index, array, iterator) {
        var previousValue = array[index];
        for (var i = 0; i < 10; ++i) {
            array[index] = i;
            if (index == array.length - 1) {
                iterator(array);
            } else {
                iterareIndex(index + 1, array, iterator);
            }
        }
        array[index] = previousValue;
    }
    
    function IterateCascade2(array){
        iterareIndex(0, array, logArray);
    }
    

    顺便说一句,这会给你同样的输出,而且可能更短:

    var size = 3;
    var prefix = '';
    for(var i = 0; i < size; ++i) {
        prefix += '0';
    }
    for(var i = 0, l = Math.pow(10, 3); i < l; ++i){
        var printableValue = (prefix+i).slice(-size);
        console.log(printableValue);
    }
    

    【讨论】:

    • 很好的答案!实际上,我的问题中的示例是更大程序的一部分,这就是为什么在我的情况下,您给出的第一个解决方案就是我需要的。
    猜你喜欢
    • 2010-12-21
    • 2016-09-04
    • 2020-06-29
    • 2013-03-03
    • 1970-01-01
    • 2011-12-12
    • 2016-03-23
    • 2018-05-16
    • 1970-01-01
    相关资源
    最近更新 更多