繁体   English   中英

从0到数字循环并遍历数组中的所有数字(javascript)

[英]Loop from 0 to a number and loop through all numbers in array (javascript)

这里是想法:

var a = [4, 5, 6];
for (var m = 0; m < a[0]; m++)
  for (var n = 0; n < a[1]; n++)
    for (var p = 0; p < a[2]; p++)
      console.log(`${m} + ${n} + ${p} = ${m+n+p}`);

实时复制:

 // This just tells the Stack Snippets in-snippet console not // to throw away entries once it reaches a max (the default max // is just the last 50 logs). console.config({maxEntries: Infinity}); var a = [4, 5, 6]; for (var m = 0; m < a[0]; m++) for (var n = 0; n < a[1]; n++) for (var p = 0; p < a[2]; p++) console.log(`${m} + ${n} + ${p} = ${m+n+p}`); 
 /* This just makes the console take up the full output area */ .as-console-wrapper { max-height: 100% !important; } 

如果数组a具有更多索引,则代码将变得更长。 是否可以使用Array.map或filter或函数来缩短代码?

如果将其分解,会更容易。 首先,您需要为数组的每个元素创建一个序列。

let series = num => Array.from({ length: num + 1 }, (n, i) => i); //creates an array with nums from  0 to num.

那是你问题的第一部分。 然后,您需要制作系列的叉积。

基本上,对于两个系列[1, 2, 3][1, 2, 3, 4]您将得到一组12个元素:

[2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7]

为此,您可以执行以下操作:

let crossProduct = (a1, a2) => Array.prototype.concat.call(...a1.map(n1 => a2.map(n2 => n1 + n2)));

现在,您需要做的就是每个系列都有一个crossProduct

let final = numbers.map(series).reduce(crossProduct);

那里有:

 let numbers = [4, 5, 6]; let series = num => Array.from({ length: num + 1 }, (n, i) => i); let crossProduct = (a1, a2) => Array.prototype.concat.call(...a1.map(n1 => a2.map(n2 => n1 + n2))); let final = numbers.map(series).reduce(crossProduct); console.log(final); 

编辑:如果它是从0到之前的数字(例如4是[0,1,2,3]),则只需在系列函数中加上+ 1

第二编辑:为您的crossProduct创建的对象crossProduct

let crossProduct = (a1, a2) => {
    let resultingSet = [];
    for(let i = 0; i < a1.length; i++)
        for(let j = 0; j < a2.length; j++)
            resultingSet.push(a1[i] + a2[j]);
    return resultingSet;
} //only one array is created

而且,如果您要避免一直将序列存储在内存中,请执行以下操作:

  let numbers = [4, 5, 6]; let series = function* (num){ for(let i = 0; i < num; i++){ yield i; } } let crossProduct = (set, num) => { let resultingSet = []; for(let i = 0; i < set.length; i++){ for(let j of series(num)){ resultingSet.push(set[i] + j); } } return resultingSet; } let final = numbers.reduce(crossProduct, [0]); console.log(final); 

通过使用递归,我们可以在不占用大量内存的情况下轻松地做到这一点:

const process = (array, n, numbers) => {
    if (n < array.length) {
        // Not done yet, recurse once for each number at this level
        const max = array[n];
        for (let i = 0; i < max; ++i) {
            process(array, n + 1, [...numbers, i]);
        }
    } else {
        // Done with this level, process the numbers we got
        console.log(`${numbers.join(" + ")} = ${numbers.reduce((s, e) => s + e)}`);
    }
}

process([4, 5, 6], 0, []);

实时复制,通过对您的结果进行交叉检查来确保上述操作具有相同的作用:

 // This just tells the Stack Snippets in-snippet console not // to throw away entries once it reaches a max (the default max // is just the last 50 logs). console.config({maxEntries: Infinity}); function thisSolution() { const results = []; const process = (array, n, numbers) => { if (n < array.length) { // Not done yet, recurse once for each number at this level const max = array[n]; for (let i = 0; i < max; ++i) { process(array, n + 1, [...numbers, i]); } } else { // Done with this level, process the numbers we got const result = numbers.reduce((s, e) => s + e); results.push(result); console.log(`${numbers.join(" + ")} = ${result}`); } } process([4, 5, 6], 0, []); return results; } function yourSolution() { const results = []; var a = [4, 5, 6]; for (var m = 0; m < a[0]; m++) for (var n = 0; n < a[1]; n++) for (var p = 0; p < a[2]; p++) results.push(m + n + p); return results; } const thisResult = thisSolution(); const yourResult = yourSolution(); if (thisResult.some((entry, index) => entry !== yourResult[index])) { console.log("WRONG"); } else { console.log("RIGHT"); } 
 /* This just makes the console take up the full output area */ .as-console-wrapper { max-height: 100% !important; } 

这永远不会深入到堆栈中(准确地说,是a.length + 1个堆栈帧,因此在示例中为4个)。 它建立了许多临时数组(在本例中为145个),这些数组在a.length个条目中达到最大值,并在不再需要它们时立即释放它们(在任何给定时间最多保留四个)。 这是快速而肮脏的指标:

 let maxStack = 0; let stack = 0; let totalArrays = 0; let maxArrays = 0; let arrays = 0; // A wrapper for counting stack frames const process = (...args) => { if (++stack > maxStack) { maxStack = stack; } const result = process2(...args); --stack; return result; }; const process2 = (array, n, numbers) => { if (n < array.length) { // Not done yet, recurse once for each number at this level const max = array[n]; for (let i = 0; i < max; ++i) { ++totalArrays; if (++arrays > maxArrays) { maxArrays = arrays; } process(array, n + 1, [...numbers, i]); --arrays; } } else { // Done with this level, process the numbers we got //console.log(`${numbers.join(" + ")} = ${numbers.reduce((s, e) => s + e)}`); } } process([4, 5, 6], 0, []); ++maxArrays; // To account for the one in the last argument above ++totalArrays; // " console.log(`Max stack: ${maxStack}, max arrays: ${maxArrays}, total arrays: ${totalArrays}`); 

另一种不消耗大量内存且相当高效的解决方案是使用表示索引值并在每次迭代中对其进行更新的数组。 首先,您创建一个数组,该数组表示每个元素中分别需要运行的迭代次数以分别更新索引,例如,对于此数组[1, 2, 3 ,4 ,5]您将得到: [280, 140, 20, 5, 1]这意味着index [0]将每280次迭代更新,index [1]将每140次迭代更新,依此类推..总共,您将运行arr [n] * arr [n-1] * arr [n-2] * .... * arr [0]迭代,就像使用普通的嵌套for循环所做的那样。

var arr = [1, 2, 7, 4, 5];

var indexes = Array.from({length: arr.length}, () => 0);
iterationsPerElement = arr.map((_, i) => arr.slice(i+1).reduce((acc, elem) => acc * elem, 1));

var totalIterations = iterationsPerElement[0] * arr[0];

for(var iteration = 1; iteration <= totalIterations; iteration++) {
    // sum those indexes
    console.log(`sum = ${indexes.reduce((acc, index) => acc + index, 0)}`);

    // update indexes
    for(i = 0; i < indexes.length; i++) {
        if(iteration % iterationsPerElement[i] == 0) {
            indexes[i]++;
            // empty the indexes on the right
            for(var j=i+1; j <indexes.length; j++) {
                indexes[j] = 0;
            }
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM