Javascript交换数组元素

ken*_*ken 199 javascript arrays

有没有更简单的方法来交换数组中的两个元素?

var a = list[x], b = list[y];
list[y] = a;
list[x] = b;
Run Code Online (Sandbox Code Playgroud)

tva*_*son 343

您只需要一个临时变量.

var b = list[y];
list[y] = list[x];
list[x] = b;
Run Code Online (Sandbox Code Playgroud)

10年后编辑劫持最佳答案,我们正在采用大量ES6:

给定数组arr = [1,2,3,4],您可以在一行中交换值,如下所示:

[arr[0], arr[1]] = [arr[1], arr[0]];
Run Code Online (Sandbox Code Playgroud)

这会产生数组[2,1,3,4].这是解构分配.

  • 有人可以向我解释为什么 `[arr[1], arr[0]]` 会改变原始数组吗?这对我来说似乎难以置信。 (6认同)
  • 在这种情况下,es6 表达式可能效率低下,因为它会生成新的、不必要的数组分配。 (5认同)
  • 即使不使用 ECMAScript 6 解构赋值,实际上也可以实现同步交换,而不会用临时变量污染当前范围:`a = [b, b = a][0];` 正如@Jan 所指出的,尽管我仍然发现自己使用临时变量方法,因为它是跨语言的(例如 C/C++),并且通常是我想到的第一种方法。 (3认同)
  • @YerkoPalma-表达式返回[2,1],但是原始数组将被突变为[2,1,3,4] (3认同)
  • 您可以与es6交换就位(变异),如下所示:`[list [y],list [x]] = [list [x],list [y]];` (2认同)

ken*_*bec 107

如果您想要一个表达式,使用本机javascript,请记住,拼接操作的返回值包含已删除的元素.

var A = [1, 2, 3, 4, 5, 6, 7, 8, 9], x= 0, y= 1;
A[x] = A.splice(y, 1, A[x])[0];
alert(A); // alerts "2,1,3,4,5,6,7,8,9"
Run Code Online (Sandbox Code Playgroud)

编辑:

[0]是在作为表达式的结尾必要Array.splice()返回一个数组,并且在这种情况下,我们所需要的返回数组中的单个元件.

  • splice大约是常规交换http://jsperf.com/js-list-swap的两倍 (21认同)
  • splice返回一个数组.所以在你的例子中,在交换操作之后你的数组看起来像:[[2],1,3,4,5,6,7,8,9] (3认同)

Ste*_*fan 71

这似乎没问题....

var b = list[y];
list[y] = list[x];
list[x] = b;
Run Code Online (Sandbox Code Playgroud)

Howerver使用

var b = list[y];
Run Code Online (Sandbox Code Playgroud)

表示将在范围的其余部分存在b变量.这可能会导致内存泄漏.不太可能,但更好的避免.

将它放入Array.prototype.swap可能是一个好主意

Array.prototype.swap = function (x,y) {
  var b = this[x];
  this[x] = this[y];
  this[y] = b;
  return this;
}
Run Code Online (Sandbox Code Playgroud)

可以这样称为:

list.swap( x, y )
Run Code Online (Sandbox Code Playgroud)

这是避免内存泄漏DRY的干净方法.

  • 难道你不能通过将其包装在函数中来避免"潜在的内存泄漏"吗? (5认同)
  • 为了避免潜在的“变平”事故,我不会碰任何内置类型的原型链。 (2认同)

Dav*_*ary 50

根据Metafilter的一些随机人士的说法,"Javascript的最新版本允许你更加巧妙地进行交换(以及其他事情):"

[ list[x], list[y] ] = [ list[y], list[x] ];
Run Code Online (Sandbox Code Playgroud)

我的快速测试表明,这个Pythonic代码在目前用于"Google Apps Script"(".go")的JavaScript版本中运行良好.唉,进一步的测试显示这段代码给出了"未捕获的ReferenceError:赋值中的左侧无效".在谷歌浏览器版本24.0.1312.57 m使用的任何版本的JavaScript(".js").

  • 喜欢这个解决方案。清洁,如预期。太糟糕了,这个问题是 9 年前提出的... (3认同)
  • 这是ES6提案的一部分:它尚未正式化,因此不应该绝对假设它在任何地方都可以工作(如果它确实......那就太棒了). (2认同)
  • 它适用于当前的firefox最新版本(39.0.3). (2认同)
  • 它适用于Chrome版本54.0.2840.71及更早版本.此外,如果你使用ES6转发器,如[babel](https://babeljs.io/),这应该是你的代码. (2认同)
  • 它已在 es6 中标准化,此功能称为解构。 (2认同)

Mar*_*ell 28

好吧,你不需要缓冲两个值 - 只有一个:

var tmp = list[x];
list[x] = list[y];
list[y] = tmp;
Run Code Online (Sandbox Code Playgroud)

  • 'tmp'听起来比'b'听起来更合理 (11认同)
  • @ofir_aghai是的,你是对的:10多年前,另一个答案在这个答案之前**22秒**发布(12:14:16Z vs 12:14:38Z)... (2认同)

Jan*_*Jan 21

您可以通过以下方式交换数组中的元素:

list[x] = [list[y],list[y]=list[x]][0]
Run Code Online (Sandbox Code Playgroud)

请参阅以下示例:

list = [1,2,3,4,5]
list[1] = [list[3],list[3]=list[1]][0]
//list is now [1,4,3,2,5]
Run Code Online (Sandbox Code Playgroud)

注意:对于常规变量,它的工作方式相同

var a=1,b=5;
a = [b,b=a][0]
Run Code Online (Sandbox Code Playgroud)

  • 这与在ES6(下一版JavaScript)中执行此操作的标准正确方法非常类似:`[list [x],list [y]] = [list [y],list [x]];`. (6认同)

Jak*_*old 18

使用数字值,您可以通过使用按位xor来避免临时变量

list[x] = list[x] ^ list[y];
list[y] = list[y] ^ list[x];
list[x] = list[x] ^ list[y];
Run Code Online (Sandbox Code Playgroud)

或算术和(注意这仅在x + y小于数据类型的最大值时才有效)

list[x] = list[x] + list[y];
list[y] = list[x] - list[y];
list[x] = list[x] - list[y];
Run Code Online (Sandbox Code Playgroud)

  • 这只适用于数值,不是吗? (8认同)
  • 出了点问题.不是`list [y] = list [x] - list [x];`只是等于`list [y] = 0;`? (7认同)
  • 当x = y时,xor技巧也会失败 - 它将list [x]设置为零,当你可能期望它将list [x]保持为原始值时. (3认同)
  • 那个darth和vader一样吗?+1 (2认同)
  • 从技术上讲,您可以创建一个临时值,只是不要将其移动到数组的相关区域之外。 (2认同)
  • 既不简单,也不高效,也不通用。 (2认同)
  • 这在 C 语言中可能是可以接受的,但在 Javascript 中却不是很好。如果可以保证元素的某些属性,例如它们都是整数,则只能将其视为交换。即使使用算术版本,浮点数也很可能会导致精度损失。是的,这也非常不清楚。至少这个答案的最初版本承认它很糟糕。 (2认同)

dir*_*dig 16

当提出问题时,这不存在,但ES2015引入了数组解构,允许您按如下方式编写:

let a = 1, b = 2;
// a: 1, b: 2
[a, b] = [b, a];
// a: 2, b: 1
Run Code Online (Sandbox Code Playgroud)

  • 要像这样在数组内交换:`[list [x],list [y]] = [list [y],list [x]]; ` (12认同)

小智 13

摘自http://www.greywyvern.com/?post=265

var a = 5, b = 9;    
b = (a += b -= a) - b;    
alert([a, b]); // alerts "9, 5"
Run Code Online (Sandbox Code Playgroud)

  • 仅适用于整数 (2认同)

小智 13

交换两个连续的数组元素

array.splice(IndexToSwap,2,array[IndexToSwap+1],array[IndexToSwap]);
Run Code Online (Sandbox Code Playgroud)


ROR*_*ROR 10

那么Destructuring_assignment呢

var arr = [1, 2, 3, 4]
[arr[index1], arr[index2]] = [arr[index2], arr[index1]]
Run Code Online (Sandbox Code Playgroud)

这也可以扩展到

[src order elements] => [dest order elements]
Run Code Online (Sandbox Code Playgroud)


dan*_*lmo 7

您可以使用这样的简单标识函数交换任意数量的对象或文字,甚至是不同类型的文字:

var swap = function (x){return x};
b = swap(a, a=b);
c = swap(a, a=b, b=c);
Run Code Online (Sandbox Code Playgroud)

对于你的问题:

var swap = function (x){return x};
list[y]  = swap(list[x], list[x]=list[y]);
Run Code Online (Sandbox Code Playgroud)

这适用于JavaScript,因为即使未声明或使用它们,它也会接受其他参数.a=ba传递给函数之后发生的赋值等.


She*_*tor 7

考虑这样的解决方案而无需定义第三个变量:

function swap(arr, from, to) {
  arr.splice(from, 1, arr.splice(to, 1, arr[from])[0]);
}

var letters = ["a", "b", "c", "d", "e", "f"];

swap(letters, 1, 4);

console.log(letters); // ["a", "e", "c", "d", "b", "f"]
Run Code Online (Sandbox Code Playgroud)

注意:您可能希望添加其他检查,例如数组长度.这个解决方案是可变的,所以swap函数不需要返回一个新的数组,它只是通过传入的数组进行突变.


7vu*_*0hy 6

对于两个或更多元素(固定数量)

[list[y], list[x]] = [list[x], list[y]];
Run Code Online (Sandbox Code Playgroud)

不需要临时变量!

我在考虑简单地打电话list.reverse().
但后来我意识到它只会在交换时起作用list.length = x + y + 1.

对于可变数量的元素

我已经研究了各种现代Javascript结构,包括Mapmap,但遗憾的是没有一个代码比这种老式的基于循环的结构更紧凑或更快:

function multiswap(arr,i0,i1) {/* argument immutable if string */
    if (arr.split) return multiswap(arr.split(""), i0, i1).join("");
    var diff = [];
    for (let i in i0) diff[i0[i]] = arr[i1[i]];
    return Object.assign(arr,diff);
}

Example:
    var alphabet = "abcdefghijklmnopqrstuvwxyz";
    var [x,y,z] = [14,6,15];
    var output = document.getElementsByTagName("code");
    output[0].innerHTML = alphabet;
    output[1].innerHTML = multiswap(alphabet, [0,25], [25,0]);
    output[2].innerHTML = multiswap(alphabet, [0,25,z,1,y,x], [25,0,x,y,z,3]);
Run Code Online (Sandbox Code Playgroud)
<table>
    <tr><td>Input:</td>                        <td><code></code></td></tr>
    <tr><td>Swap two elements:</td>            <td><code></code></td></tr>
    <tr><td>Swap multiple elements:&nbsp;</td> <td><code></code></td></tr>
</table>
Run Code Online (Sandbox Code Playgroud)


fmg*_*fmg 6

这是一个不会变异的单行list

let newList = Object.assign([], list, {[x]: list[y], [y]: list[x]})

(使用 2009 年发布问题时不可用的语言功能!)


Viv*_*vek 5

有一种有趣的交换方式:

var a = 1;
var b = 2;
[a,b] = [b,a];
Run Code Online (Sandbox Code Playgroud)

(ES6方式)

  • 对于数组,则更多是`var a = [7,8,9,10],i = 2,j = 3; [a [i],a [j]] = [a [j],a [i] ];` (5认同)