我试图写一个函数,它做以下工作:

以一个整数数组作为参数(例如[1,2,3,4]) 创建一个包含[1,2,3,4]的所有可能排列的数组,每个排列的长度为4

下面的函数(我在网上找到的)通过接受一个字符串作为参数,并返回该字符串的所有排列来实现这一点

我不知道如何修改它,使它与整数数组一起工作,(我认为这与一些方法在字符串上的工作方式不同于在整数上的工作方式有关,但我不确定…)

let permArr = [];
let usedChars = [];

function permute(input) {
    const chars = input.split("");
    for (let i = 0; i < chars.length; i++) {
        const ch = chars.splice(i, 1);
        usedChars.push(ch);
        if (chars.length === 0) {
            permArr[permArr.length] = usedChars.join("");
        }
        permute(chars.join(""));
        chars.splice(i, 0, ch);
        usedChars.pop();
    }
    return permArr
};

注意:我希望函数返回整数数组,而不是字符串数组。

我真的需要解决方案是在JavaScript。我已经知道如何在python中做到这一点


当前回答

  let permutations = []

  permutate([], {
    color: ['red', 'green'],
    size: ['big', 'small', 'medium'],
    type: ['saison', 'oldtimer']
  })

  function permutate (currentVals, remainingAttrs) {
    remainingAttrs[Object.keys(remainingAttrs)[0]].forEach(attrVal => {
      let currentValsNew = currentVals.slice(0)
      currentValsNew.push(attrVal)

      if (Object.keys(remainingAttrs).length > 1) {
        let remainingAttrsNew = JSON.parse(JSON.stringify(remainingAttrs))
        delete remainingAttrsNew[Object.keys(remainingAttrs)[0]]

        permutate(currentValsNew, remainingAttrsNew)
      } else {
        permutations.push(currentValsNew)
      }
    })
  }

结果:

[ 
  [ 'red', 'big', 'saison' ],
  [ 'red', 'big', 'oldtimer' ],
  [ 'red', 'small', 'saison' ],
  [ 'red', 'small', 'oldtimer' ],
  [ 'red', 'medium', 'saison' ],
  [ 'red', 'medium', 'oldtimer' ],
  [ 'green', 'big', 'saison' ],
  [ 'green', 'big', 'oldtimer' ],
  [ 'green', 'small', 'saison' ],
  [ 'green', 'small', 'oldtimer' ],
  [ 'green', 'medium', 'saison' ],
  [ 'green', 'medium', 'oldtimer' ] 
]

其他回答

我写了一篇文章来演示如何在JavaScript中排列数组。下面是执行此操作的代码。

var count=0;
function permute(pre,cur){ 
    var len=cur.length;
    for(var i=0;i<len;i++){
        var p=clone(pre);
        var c=clone(cur);
        p.push(cur[i]);
        remove(c,cur[i]);
        if(len>1){
            permute(p,c);
        }else{
            print(p);
            count++;
        }
    }
}
function print(arr){
    var len=arr.length;
    for(var i=0;i<len;i++){
        document.write(arr[i]+" ");
    }
    document.write("<br />");
}
function remove(arr,item){
    if(contains(arr,item)){
        var len=arr.length;
        for(var i = len-1; i >= 0; i--){ // STEP 1
            if(arr[i] == item){             // STEP 2
                arr.splice(i,1);              // STEP 3
            }
        }
    }
}
function contains(arr,value){
    for(var i=0;i<arr.length;i++){
        if(arr[i]==value){
            return true;
        }
    }
    return false;
}
function clone(arr){
    var a=new Array();
    var len=arr.length;
    for(var i=0;i<len;i++){
        a.push(arr[i]);
    }
    return a;
}

就叫

permute([], [1,2,3,4])

将工作。关于这是如何工作的详细信息,请参考那篇文章中的解释。

为了解决这个问题,我的想法如下…

1- (n)的总排列是(n!)

2-检查组合小n (n <= 4)。

3-应用递归技术。

if(n == 1) // ['a']
    then permutation is (1) ['a']
if(n == 2) // ['a', 'b']
    then permutations are (2) ['a', 'b'] ['b', 'a']
if(n == 3) // ['a', 'b', 'c']
    then permutations are (6) ['a', 'b', 'c'] ['a', 'c', 'b'] ['b', 'a', 'c'] ['b', 'c', 'a'] ['c', 'a', 'b'] ['c', 'b', 'a']

所以…排列行为是有规律的。

和数组实例的总排列是…所有可能的子排列从原始数组中移除每个单个字符,并将该单个字符与它们相对的子排列连接起来。也许代码能更好地解释这一点。

Bye!

function permutations(array) { let permutationList = []; if(array.length == 1) { return array; } for(let i = 0; i < array.length; i++) { let arrayLength1 = [ array[i] ]; let auxArray = Object.values(array); auxArray.splice(i, 1); let subPermutations = this.permutations(auxArray); for(let j = 0; j < subPermutations.length; j++) { let arrayMerge = arrayLength1.concat(subPermutations[j]); permutationList.push(arrayMerge); } } return permutationList; } let results4 = permutations(['a', 'b' ,'c', 'd']); let results6 = permutations(['a', 'b' ,'c', 'd', 'e', 'f']); console.log(results4.length); console.log(results4); console.log(results6.length); console.log(results6);

我改进了SiGanteng的答案。

现在可以多次调用permute,因为permArr和usedChars每次都被清除。

function permute(input) {
    var permArr = [],
        usedChars = [];
    return (function main() {
        for (var i = 0; i < input.length; i++) {
            var ch = input.splice(i, 1)[0];
            usedChars.push(ch);
            if (input.length == 0) {
                permArr.push(usedChars.slice());
            }
            main();
            input.splice(i, 0, ch);
            usedChars.pop();
        }
        return permArr;
    })();
}

函数排列(输入) { var permArr = [], 使用的字符 = []; return (函数 main() { for (var i = 0; i < input.length; i++) { var ch = input.splice(i, 1)[0]; usedChars.push(ch); if (input.length == 0) { permArr.push(usedChars.slice()); } 主(); input.splice(i, 0, ch); usedChars.pop(); } 返回permArr; })(); } document.write(JSON.stringify(permute([5, 3, 7, 1])));

我认为下面的解决方案的唯一不同之处在于,我在出现空情况前一步停止了递归。希望嵌入的评论是充分的解释。

function Permutations (A) // computes all possible ordered sequences of the entries in array A and returns them as an array of arrays
{
var perms = [];

for (var i = 0 ; i < A.length ; i++)
    {
    var rem = A.slice (0); // copy input array to retain remainder of elements after removing i'th element
    var el = rem.splice (i,1);
    if (A.length == 2) {perms.push ([el [0],rem [0]])} // recursion end case
    else 
        {
        var sub = Permutations (rem); // recursive call
        for (var s = 0 ; s < sub.length ; s++) // process recursive response, adding el to the start of each returned sequence
            {
            sub [s].splice (0,0,el [0]);
            perms.push (sub [s]);
            };
        };
    };

return perms ;

};// end of Permutations function

一些受到Haskell启发的版本:

perms [] = [[]]
perms xs = [ x:ps | x <- xs , ps <- perms ( xs\\[x] ) ]

function perms(xs) { if (!xs.length) return [[]]; return xs.flatMap(x => { // get permutations of xs without x, then prepend x to each return perms(xs.filter(v => v!==x)).map(vs => [x, ...vs]); }); // or this duplicate-safe way, suggested by @M.Charbonnier in the comments // return xs.flatMap((x, i) => { // return perms(xs.filter((v, j) => i!==j)).map(vs => [x, ...vs]); // }); // or @user3658510's variant // return xs.flatMap((x, i) => { // return perms([...xs.slice(0,i),...xs.slice(i+1)]).map(vs => [x,...vs]); // }); } document.write(JSON.stringify(perms([1,2,3])));