Javascript - 是否有更有效的方法来创建数组数组? - 提供的例子

Javascript - Is there a more efficient way to create an array of arrays? - Examples provided

问题:是否有更有效的方法来创建递增数组的数组?

我创建了一个函数来生成递增数字数组的数组,这比预期的要长得多,而且我确信有更有效的方法来实现这一点(我是 JS 新手) .

示例 1 和示例 2 的 genArray 函数注意事项: argu1 声明数字范围的开始(例如 0 = 从 0 开始), argu2 声明数字范围的结束(例如 9 = 结束于 9), argu3 声明每个单独的数组中需要多少个数字(例如 3 = 在数组中生成 3 个数字), argu4携带临时数组生成单个数字数组, argu5通过函数和嵌套函数携带数组的数组

示例 1:下面是纯粹用于创建递增数字数组数组的代码。我的问题是关于制作此功能的更高效版本。

function genArray(start, finish, quantity, array, allArray = []) {
  var collectArray = allArray;

  //Cycle through digits from start to finish, e.g. 0-9
  for (var i = start; i <= finish; i++) {
    var tempArray = [];

    //Collect digits for a single array if not first iteration
    if (array !== undefined) {
      tempArray = tempArray.concat(array);
    };

    //Add digit to single level array
    tempArray.push(i);

    //If not highest level, go higher
    if (quantity > 1) {
      var genArray2 = genArray(start, finish, quantity-1, tempArray, collectArray);
    } 

    //If highest level collect a single array
    else if (quantity == 1) {
      collectArray.push(tempArray);
    }
  }
  return collectArray;
}

//Call function with arguments
//argu1 declares the start of the number range, argu2 declares the end of the number range, argu3 declares how many numbers are needed in each individual array, argu4 carrays the temp array to generate a single array of numbers, argu4 carrys the array of arrays throught the function and nested functions. 
var genArray2 = genArray(0, 9, 3);
console.log(genArray2);

这会生成如下日志:

[ [ 0, 0, 0 ],
  [ 0, 0, 1 ],
  [ 0, 0, 2 ],
  [ 0, 0, 3 ],
  [ 0, 0, 4 ],
  [ 0, 0, 5 ],
  [ 0, 0, 6 ],
  [ 0, 0, 7 ],
  [ 0, 0, 8 ],
  [ 0, 0, 9 ],
  [ 0, 1, 0 ],
  [ 0, 1, 1 ],
  [ 0, 1, 2 ],
  [ 0, 1, 3 ],
  [ 0, 1, 4 ],
  [ 0, 1, 5 ],
  [ 0, 1, 6 ],
  [ 0, 1, 7 ],
  [ 0, 1, 8 ],
  [ 0, 1, 9 ],
  [ 0, 2, 0 ],
  [ 0, 2, 1 ],
  [ 0, 2, 2 ],
  [ 0, 2, 3 ],
  [ 0, 2, 4 ],
  [ 0, 2, 5 ],
  [ 0, 2, 6 ],
  [ 0, 2, 7 ],
  [ 0, 2, 8 ],
  [ 0, 2, 9 ],
  [ 0, 3, 0 ],
  [ 0, 3, 1 ],
  [ 0, 3, 2 ],
  [ 0, 3, 3 ],
  [ 0, 3, 4 ],
  .... up to [ 9, 9, 9 ]

示例 2:下面是我实际使用的代码,唯一的变化是添加了检查以查看生成的数组是否在升序并且每个数字都是唯一的,并且只存储在两种情况下都为真的那些。为上下文提供这个,以防它对某人有用:

//Check if ascending
function ascending(x) {
  return x == parseInt(x.toString().split('').sort().join(''));
}

//Check if unique
function unique(x) {
  return x.toString().split('').length == [...new Set(x)].length
}

//Create an array of arrays of ascending and unique numbers    
function genArray(start, finish, quantity, array, allArray = []) {
  var collectArray = allArray;

  //Cycle through digits from start to finish, e.g. 0-9
  for (var i = start; i <= finish; i++) {
    var tempArray = [];

    //Collect digits for a single array if not first iteration
    if (array !== undefined) {
      tempArray = tempArray.concat(array);
    };

    //Add digit to single level array
    tempArray.push(i);

    //If not highest level, go higher
    if (quantity > 1) {
      var genArray2 = genArray(start, finish, quantity-1, tempArray, collectArray);
    } 

    //If highest level collect a single array
    else if (quantity == 1 && ascending(tempArray.join('')) && unique(tempArray.join(''))) {
      collectArray.push(tempArray);
    }
  }
  return collectArray;
}

//Call function with arguments
var genArray2 = genArray(0, 9, 3);
console.log(genArray2);

这会生成如下日志:

[ [ 0, 1, 2 ],
  [ 0, 1, 3 ],
  [ 0, 1, 4 ],
  [ 0, 1, 5 ],
  [ 0, 1, 6 ],
  [ 0, 1, 7 ],
  [ 0, 1, 8 ],
  [ 0, 1, 9 ],
  [ 0, 2, 3 ],
  [ 0, 2, 4 ],
  [ 0, 2, 5 ],
  [ 0, 2, 6 ],
  [ 0, 2, 7 ],
  [ 0, 2, 8 ],
  [ 0, 2, 9 ],
  [ 0, 3, 4 ],
  [ 0, 3, 5 ],
  [ 0, 3, 6 ],
  [ 0, 3, 7 ],
  [ 0, 3, 8 ],
  [ 0, 3, 9 ],
  [ 0, 4, 5 ],
  [ 0, 4, 6 ],
  [ 0, 4, 7 ],
  [ 0, 4, 8 ],
  [ 0, 4, 9 ],
  [ 0, 5, 6 ],
  [ 0, 5, 7 ],
  [ 0, 5, 8 ],
  [ 0, 5, 9 ],
  [ 0, 6, 7 ],
  [ 0, 6, 8 ],
  [ 0, 6, 9 ],
  [ 0, 7, 8 ],
  [ 0, 7, 9 ],
  [ 0, 8, 9 ],
  [ 1, 2, 3 ],
  [ 1, 2, 4 ],
  [ 1, 2, 5 ],
  [ 1, 2, 6 ],
  .... up to [ 7, 8, 9 ]

如果您愿意做一点数学运算,一般来说,有一种非常快速简单的方法可以做到这一点。基本见解是像 768 这样的数字可以分解为取模 10 的各种 log10 组件。例如 Math.floor(768/100) % 10 得到第三个数字。 Math.floor(768/10) % 10 给你第二个。要获得所需的内部数组的长度,可以取 Math.floor(Math.log10(largestNumber + 1))。所以对于 1000 这将是 4,对于 999 这将是 3,等等。这种排列的唯一烦人的部分是数组是从左到右构建的,但数字是从右到左构建的。这就是为什么我们在内部数组中使用长度 - 索引。

您可以将其与 Array.from 放在一起以创建一个简洁的函数,从而避免大量的字符串解析和 if/else 子句:

function genArray(start, finish) {
  return Array.from({length: finish - start + 1}, (_, i) => {
    let ind = i + start
    let innerLength = Math.floor(Math.log10(finish + 1))
    return Array.from({length: innerLength + 1}, (_, i) => Math.floor(ind / (10 ** (innerLength - i))) % 10)
  })
}

let a = genArray(0, 20)
console.log(a.join(' · '))

a = genArray(1020, 1040)
console.log(a.join(' · '))

此外,不清楚您的数组有多大,但如果您处理大量数字,制作生成器可能会提高内存效率,因此您只根据需要生成内部数组。这不是对所有事情都是正确的解决方案,但由于它几乎是相同的代码,我想我会提到它:

function* genArray(start, finish) {
  let innerLength = Math.floor(Math.log10(finish + 1))
  while (start <= finish) {
    yield Array.from({length: innerLength + 1}, (_, i) => Math.floor(start / (10 ** (innerLength - i))) % 10)
    start++
  }
}
let a = genArray(101, 105)
console.log(a.next().value)

let b = genArray(20, 30)
console.log([...b].join(' · '))

我的英语不是很好,希望能理解你的问题。

从您提供的示例来看,您似乎只需要一个 2 级数组,第一个包含 n 个递增数字数组。

不是使用递归函数,它会占用大量内存,您可以尝试使用正常的 for 循环,并拆分每个数字,用 0 填充以获得 n 长度。不知道是否它可以为你工作。

0002.split 创建数组 [0,0,0,2].. 然后将它推到主数组

应该是最快的方法

//s start, e end, n array size
f=new Array();
a=new Array();
for (i=s; i<e; i++) {
 t=pad(i,n);
 a=i.toString().split('');
 f[f.length]=a;
}

function pad(s,n) { 
   while (s.length < n) 
      s = '0' + s; 
   return s; 
};

干杯 丹妮尔

这是一个可能的解决方案:

function genArrays(start, end){
    let max_len = String(end).length;
    let arr = [];
    let cur_num = start;
    let arr_num;

    for (let i = start; i <= end; i++){
        str_num = String(cur_num).padStart(max_len, '0').split('').map(x => parseInt(x));

        arr.push(str_num);

        cur_num++;
    }
    
    return arr;
}

console.log(genArrays(0, 1000));
console.log(genArrays(102, 1043));

核心在这里:str_num = String(cur_num).padStart(max_len, '0');。首先对计数器进行串接,然后在左侧应用填充以达到串接的长度 end.

如果没有递归,您将能够加快速度。这是一个循环,它只使用先前添加的子数组来计算下一个。它使用将 1 加到十进制数时的机制:首先递增最右边的数字。如果超出范围(十进制:变为 10),则将其设置回最低位并递增其左侧的数字,...等,直到最后更改的数字保持在范围内:

function genArray(start, finish, quantity) {
    const current = Array(quantity).fill(start);
    const result = [];
    for (let i = quantity; i >= 0; null) {
        result.push(current.slice());
        for (i = quantity; i--; null) {
            current[i]++;
            if (current[i] <= finish) break; 
            current[i] = start;
        }
    }
    return result;
}

console.log(genArray(0, 2, 3));