如何在JavaScript中不使用全局变量而生成置换对?

如何在JavaScript中不使用全局变量而生成置换对?,javascript,arrays,data-structures,permutation,Javascript,Arrays,Data Structures,Permutation,我需要创建一个包含所有可能的数组元素组合的数组,就像排列一个广泛分布的数据结构问题。要了解更多有关问题的信息,请访问此处,和 注意:不想使用任何JS库,只使用此处的数据结构 问题很简单,提供了一个数组,需要找到所有可能的组合,如: arr = [1,2,3]; combination = [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]; // combination.length is factorial of arr.length

我需要创建一个包含所有可能的数组元素组合的数组,就像排列一个广泛分布的数据结构问题。要了解更多有关问题的信息,请访问此处,和

注意:不想使用任何JS库,只使用此处的数据结构

问题很简单,提供了一个数组,需要找到所有可能的组合,如:

arr = [1,2,3];
combination = [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]];
// combination.length is factorial of arr.length
为了实现这一点,我创建了一个全局变量来存储组合,需要在没有全局变量的情况下执行此操作,我无法执行此操作,有人能帮我解决此问题吗,以下是我的代码:

let ans = [];  // Global variable to store combinations

function permute(arr) {
  let l = arguments[1] || 0,
      r = arguments[2] || arr.length-1;

  if (l == r) {
    let a = [];

    a.push(...arr);  // To overcome reference problem here.
    ans.push(a);
  }
  else {
    for (let i = l; i <= r; i++) {
      [arr[l], arr[i]] = [arr[i], arr[l]];  // Swap with help of new destructuring
      permute(arr, l+1, r);
      [arr[l], arr[i]] = [arr[i], arr[l]];  // Swap with help of new destructuring
    }
  }

  return ans;
}

console.log(permute([1,2,3,4]));
console.log(permute([1,2,3]));
console.log(permute([1,2,3,4,5]));
让ans=[];//用于存储组合的全局变量
函数置换(arr){
设l=arguments[1]| | 0,
r=参数[2]| | arr.length-1;
如果(l==r){
设a=[];
a、 push(…arr);//以克服此处的引用问题。
ans.push(a);
}
否则{

对于(让i=l;i您正在进行递归,而不传递累加器。为了缓解这种情况,请执行

function permuteRecursive(permutees, accumulator) {
  // if not created before, create first instance of accumulator
  accumulator = accumulator || [];

  let l = arguments[2] || 0,
      r = arguments[3] || permutees.length-1;

  if (l == r) {
    let a = [];

    a.push(...permutees);  // To overcome reference problem here.
    accumulator.push(a);
  }
  else {
    for (let i = l; i <= r; i++) {
      [permutees[l], permutees[i]] = [permutees[i], permutees[l]];  // Swap with help of new destructuring
      permuteRecursive(permutees, accumulator, l+1, r);
      [permutees[l], permutees[i]] = [permutees[i], permutees[l]];  // Swap with help of new destructuring
    }
  }

  return accumulator;
}

console.log(permuteRecursive([1,2,3,4]));
console.log(permuteRecursive([1,2,3]));
console.log(permuteRecursive([1,2,3,4,5]));
函数permuteRecursive(permutees,累加器){
//如果之前未创建,请创建累加器的第一个实例
累加器=累加器| |[];
设l=arguments[2]| | 0,
r=参数[3]| | permutees.length-1;
如果(l==r){
设a=[];
a、 push(…permutees);//来解决这里的引用问题。
蓄能器。推动(a);
}
否则{

对于(让i=l;i您正在进行递归,而不传递累加器。为了缓解这种情况,请执行

function permuteRecursive(permutees, accumulator) {
  // if not created before, create first instance of accumulator
  accumulator = accumulator || [];

  let l = arguments[2] || 0,
      r = arguments[3] || permutees.length-1;

  if (l == r) {
    let a = [];

    a.push(...permutees);  // To overcome reference problem here.
    accumulator.push(a);
  }
  else {
    for (let i = l; i <= r; i++) {
      [permutees[l], permutees[i]] = [permutees[i], permutees[l]];  // Swap with help of new destructuring
      permuteRecursive(permutees, accumulator, l+1, r);
      [permutees[l], permutees[i]] = [permutees[i], permutees[l]];  // Swap with help of new destructuring
    }
  }

  return accumulator;
}

console.log(permuteRecursive([1,2,3,4]));
console.log(permuteRecursive([1,2,3]));
console.log(permuteRecursive([1,2,3,4,5]));
函数permuteRecursive(permutees,累加器){
//如果之前未创建,请创建累加器的第一个实例
累加器=累加器| |[];
设l=arguments[2]| | 0,
r=参数[3]| | permutees.length-1;
如果(l==r){
设a=[];
a、 push(…permutees);//来解决这里的引用问题。
蓄能器。推动(a);
}
否则{

对于(设i=l;i如果唯一关心的是全局变量,您可以简单地将其包装在另一个函数中,我的意思如下:

函数置换(\u arr){
设ans=[];
(功能分配(arr){
设l=arguments[1]| | 0,
r=参数[2]| | arr.length-1;
如果(l==r){
设a=[];
a、 push(…arr);//以克服此处的引用问题。
ans.push(a);
}
否则{

对于(设i=l;i如果唯一关心的是全局变量,您可以简单地将其包装在另一个函数中,我的意思如下:

函数置换(\u arr){
设ans=[];
(功能分配(arr){
设l=arguments[1]| | 0,
r=参数[2]| | arr.length-1;
如果(l==r){
设a=[];
a、 push(…arr);//以克服此处的引用问题。
ans.push(a);
}
否则{

对于(设i=l;i我将使用一个附加参数将当前选择的元素传递给函数,并使用一个生成器将所有结果传递回:

 function* permutations(array, positions = [], previous = []) {
  if(previous.length === array.length) yield previous;

  for(let i = 0; i < array.length; i++) {
   if(positions.includes(i)) continue;

   const chosen = array[i];
   yield* permutations(array, [...positions, i], [...previous, chosen]);
  }
}

const permutate = arr => [...permutations(arr)];
函数*排列(数组,位置=[],上一个=[]){
如果(previous.length==array.length)产生previous;
for(设i=0;i[…置换(arr)];

我将使用一个附加参数将当前选择的元素传递给函数,并使用一个生成器将所有结果传递回:

 function* permutations(array, positions = [], previous = []) {
  if(previous.length === array.length) yield previous;

  for(let i = 0; i < array.length; i++) {
   if(positions.includes(i)) continue;

   const chosen = array[i];
   yield* permutations(array, [...positions, i], [...previous, chosen]);
  }
}

const permutate = arr => [...permutations(arr)];
函数*排列(数组,位置=[],上一个=[]){
如果(previous.length==array.length)产生previous;
for(设i=0;i[…置换(arr)];

另一种方法是不“向下”传递任何内容,而是重用较小子问题的结果来构建置换数组并返回该数组

因此,例如,要构建所有3个元素置换,您可以将每个元素放在第一位,并将其与其余元素的所有2个元素置换连接起来(您可以通过递归调用获得):

函数置换(arr){ if(arr.length{ var较小=置换([…arr.slice(0,i),…arr.slice(i+1)]; 较小的.forEach(p=>res.push([e].concat(p))) }); 返回res; } console.log(排列([1]);
log(排列([1,2,3]);
另一种方法是不“向下”传递任何内容,而是重用较小子问题的结果来构建排列数组并返回它

因此,例如,要构建所有3个元素置换,您可以将每个元素放在第一位,并将其与其余元素的所有2个元素置换连接起来(您可以通过递归调用获得):

函数置换(arr){ if(arr.length{ var较小=置换([…arr.slice(0,i),…arr.slice(i+1)]; 较小的.forEach(p=>res.push([e].concat(p))) }); 返回res; } console.log(排列([1]);
console.log(排列([1,2,3]);
您也可以尝试使用
Array.map
和下面的递归来实现排列。我还使用了
Array.flat
(到目前为止,Edge不支持,如果Edge浏览器支持,则需要polyfill)

函数getForwardArr(arr,i){ 返回[…arr.slice(i+1),…arr.slice(0,i)] } 函数置换(arr){ 如果(arr.length==2)返回[[…arr],arr.reverse()] 否则返回arr.map((d,i)=>permute(getForwardArr(arr,i)).map(v=>[d,v].flat()).flat() } console.log(permute([1,2])) console.log(permute([1,2,3]))
console.log(排列([1,2,3,4])
您也可以尝试使用
Array.map
和下面的递归来实现排列。我还使用了
Array.flat
(截至目前,Edge不支持,如果Edge浏览器支持,则需要polyfill)