从JavaScript数组生成2-opt交换邻域

从JavaScript数组生成2-opt交换邻域,javascript,arrays,sorting,swap,Javascript,Arrays,Sorting,Swap,我试图编写一个函数,它接受一个数组,生成所有两个交换组合,并在每次迭代时将它们添加到一个数组中,然后返回一个数组数组 我目前的执行情况: function localNeighborhood(arr) { var returnArray = []; for(i=0;i<arr.length;i++) { for(j=i;j<arr.length-1;j++) { var newArr = arr

我试图编写一个函数,它接受一个数组,生成所有两个交换组合,并在每次迭代时将它们添加到一个数组中,然后返回一个数组数组

我目前的执行情况:

function localNeighborhood(arr)
{
    var returnArray = [];

    for(i=0;i<arr.length;i++)
    {
        for(j=i;j<arr.length-1;j++)
        {
                var newArr = arr.slice();
                var toSwap = newArr[j];
                newArr[j] = newArr[j+1];
                newArr[j+1] = toSwap;
                returnArray.push(newArr);
        }
    }
    return returnArray;
}

localNeighborhood(["1", "2", "3", "4"]);
(忽略//注释,我只需要上述数组的一个数组)

但是我的代码返回的结果如下

["2", "1", "3", "4"]
["1", "3", "2", "4"]
["1", "2", "4", "3"]
["1", "3", "2", "4"]
["1", "2", "4", "3"]
["1", "2", "4", "3"]
正如您所看到的,实现就快到了,但是在某个地方出了问题。我认为嵌套循环及其计数是正确的,因为我们得到了六个结果,但实际的交换是错误的

我想将每次交换添加到我的“returnArray”。交换是在arr[i]处的每个变量与在arr[x]处的每个变量,其中x>i,因此索引0将与索引大于0的每个变量交换,而最后一个元素将仅与最后一个元素交换

非常感谢您的帮助。谢谢大家!


这是我问题的新版本,因为它被标记为生成置换的副本,但我不想生成数组的置换-我不想要4!=数组的24个置换,我想要变量的2-opt交换数组[I]交换数组[x],其中x>I。生成置换是一种简单的方法,但对于较长的阵列,需要花费太多的时间,并且会导致Chrome崩溃。虽然我的示例是一个包含4个元素的数组,但输入数组可能更长

我设法弄明白了!请参阅下文,了解如何为JavaScript数组生成2-opt交换

function localNeighborhood(arr)
{
    var returnArray = [];

    for(i=0;i<arr.length;i++)
    {
        for(j=i;j<arr.length;j++)
        {
                var newArr = arr.slice();
                var toSwap = newArr[i];
                newArr[i] = newArr[j];
                newArr[j] = toSwap;
                if(arr.toString() != newArr.toString())
                {
                    returnArray.push(newArr);
                }
        }
    }
    return returnArray;
}
将返回以下值:

["2", "1", "3", "4"]
["3", "2", "1", "4"]
["4", "2", "3", "1"]
["1", "3", "2", "4"]
["1", "4", "3", "2"]
["1", "2", "4", "3"]
这非常适合通过2-opt边交换解决旅行商问题等问题,如果您的行程表示为如上所述的数组,则函数将生成所有两个opt边交换,以便您为当前迭代评估和存储最佳的一个


希望这有帮助

您可以更改外循环的结束值,并使用递增的
i
值启动内循环

此方案不检查与上次交换相同的数组,因为只有现有索引用于交换

函数交换(数组){
var i,j,
临时雇员
结果=[];
对于(i=0;ilog(result.map(a=>JSON.stringify(a))我通常不会建议在JS中使用递归,但是为了好玩,您可以通过使用扩展和rest操作符通过解构实现Haskell式模式匹配,并可能会提出以下建议:

var doSomething=([x,…xs])=>xs.length?map((e,i)=>[e].concat(Object.assign([],xs,{[i]:x})))
.concat(doSomething(xs).map(sa=>[x].concat(sa)))
: [];
log(JSON.stringify(doSomething([1,2,3,4]))
localNeighborhood(["1", "2", "3", "4"]);
["2", "1", "3", "4"]
["3", "2", "1", "4"]
["4", "2", "3", "1"]
["1", "3", "2", "4"]
["1", "4", "3", "2"]
["1", "2", "4", "3"]