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

以一个整数数组作为参数(例如[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中做到这一点


当前回答

这是一个很短的解决方案,只适用于1或2个长字符串。它是一个联机程序,使用ES6而不依赖jQuery,速度非常快。享受:

var p = l => l.length<2 ? [l] : l.length==2 ? [l[0]+l[1],l[1]+l[0]] : Function('throw Error("unimplemented")')();

其他回答

这是我做的一个…

const permute = (ar) =>
  ar.length === 1 ? ar : ar.reduce( (ac,_,i) =>
    {permute([...ar.slice(0,i),...ar.slice(i+1)]).map(v=>ac.push([].concat(ar[i],v))); return ac;},[]);

又来了,只不过写得不那么简洁了……

function permute(inputArray) {
  if (inputArray.length === 1) return inputArray;
  return inputArray.reduce( function(accumulator,_,index){
    permute([...inputArray.slice(0,index),...inputArray.slice(index+1)])
      .map(value=>accumulator.push([].concat(inputArray[index],value)));
    return accumulator;
  },[]);
}

工作原理:如果数组比一个元素长,它会遍历每个元素,并将其与对自身的递归调用连接起来,其余元素作为参数。它不会改变原始数组。

无需外部数组或附加函数即可回答

function permutator (arr) {
  var permutations = [];
  if (arr.length === 1) {
    return [ arr ];
  }

  for (var i = 0; i <  arr.length; i++) { 
    var subPerms = permutator(arr.slice(0, i).concat(arr.slice(i + 1)));
    for (var j = 0; j < subPerms.length; j++) {
      subPerms[j].unshift(arr[i]);
      permutations.push(subPerms[j]);
    }
  }
  return permutations;
}

我对网站的第一个贡献。此外,根据我所做的测试,这段代码比在此之前提到的所有其他方法运行得更快,当然,如果值很少,它是最小的,但是当添加太多时,时间会呈指数增长。

var result = permutations([1,2,3,4]); var output = window.document.getElementById('output'); output.innerHTML = JSON.stringify(result); function permutations(arr) { var finalArr = []; function iterator(arrayTaken, tree) { var temp; for (var i = 0; i < tree; i++) { temp = arrayTaken.slice(); temp.splice(tree - 1 - i, 0, temp.splice(tree - 1, 1)[0]); if (tree >= arr.length) { finalArr.push(temp); } else { iterator(temp, tree + 1); } } } iterator(arr, 1); return finalArr; }; <div id="output"></div>

在精神上类似于@crl的haskell风格的解决方案,但使用reduce:

function permutations( base ) {
  if (base.length == 0) return [[]]
  return permutations( base.slice(1) ).reduce( function(acc,perm) {
    return acc.concat( base.map( function(e,pos) {
      var new_perm = perm.slice()
      new_perm.splice(pos,0,base[0])
      return new_perm
    }))
  },[])    
}

目前最快、最有效、最优雅的版本(2020年)

function getArrayMutations (arr, perms = [], len = arr.length) { if (len === 1) perms.push(arr.slice(0)) for (let i = 0; i < len; i++) { getArrayMutations(arr, perms, len - 1) len % 2 // parity dependent adjacent elements swap ? [arr[0], arr[len - 1]] = [arr[len - 1], arr[0]] : [arr[i], arr[len - 1]] = [arr[len - 1], arr[i]] } return perms } const arrayToMutate = [1, 2, 3, 4, 5, 6, 7, 8, 9] const startTime = performance.now() const arrayOfMutations = getArrayMutations(arrayToMutate) const stopTime = performance.now() const duration = (stopTime - startTime) / 1000 console.log(`${arrayOfMutations.length.toLocaleString('en-US')} permutations found in ${duration.toLocaleString('en-US')}s`)