Javascript交换数组元素

IT技术 javascript arrays
2021-01-28 21:07:45

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

var a = list[x], b = list[y];
list[y] = a;
list[x] = b;
6个回答

您只需要一个临时变量。

var b = list[y];
list[y] = list[x];
list[x] = b;

10 年后编辑劫持最佳答案,并在我们的腰带下采用了大量 ES6:

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

[arr[0], arr[1]] = [arr[1], arr[0]];

这将产生数组[2,1,3,4]这是解构赋值

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

如果您想要使用原生 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"

编辑:

[0]是在表达的端部必要Array.splice()的阵列的回报,并且在这种情况下,我们所需要的返回数组中的单个元件。

好又短,但正如@aelgoa 所说,几乎比简单的交换慢
2021-03-15 21:07:45
已确认,缺少 [0]。
2021-03-19 21:07:45
少了 1 个字符 [A[x]] = A.splice(y, 1, A[x])
2021-03-28 21:07:45
splice 返回一个数组。所以在你的例子中,在交换操作之后你的数组实际上看起来像:[[2], 1, 3, 4, 5, 6, 7, 8, 9]
2021-04-01 21:07:45
A[x]= A.splice(y, 1, A[x])[0]; ? 在 mootools Array.implement({ swap: function(x, y) { this[y] = this.splice(x, 1, this[y])[0]; } });
2021-04-06 21:07:45

这似乎没问题....

var b = list[y];
list[y] = list[x];
list[x] = b;

但是使用

var b = list[y];

意味着b变量将存在于范围的其余部分。这可能会导致内存泄漏。不太可能,但还是最好避免。

把它放到 Array.prototype.swap 中也许是个好主意

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

可以这样调用:

list.swap( x, y )

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

为了避免潜在的“扁平化”事故,我不会触及任何内置类型的原型链。
2021-03-16 21:07:45
@大卫R。边界检查是多余的和不必要的。如果需要,调用者拥有执行此类检查所需的一切,但在大多数情况下,您已经知道 x 和 y 处于边界内,因为您处于某种循环中。
2021-03-23 21:07:45
难道你不能通过将它包装在一个函数中来避免“潜在的内存泄漏”吗?
2021-03-26 21:07:45
我也喜欢这个。Array.implement({ swap: function(x,y) { x = this[x]; this[x] = this[y]; this[y] = x; return this; } });
2021-03-31 21:07:45
这很好。也许一些边界检查?Array.prototype.swap = function (x,y) { if (x >= 0 && x < this.length && y >= 0 && y < this.length) { var b = this[x]; this[x] = this[y]; this[y] = b; } return this; };
2021-04-08 21:07:45

根据Metafilter上的一些随机人员的说法,“最近版本的 Javascript 允许您更巧妙地进行交换(除其他外):”

[ list[x], list[y] ] = [ list[y], list[x] ];

我的快速测试表明,此Pythonic 代码在“Google Apps Script”(“.gs”)中当前使用的 JavaScript 版本中运行良好。唉,进一步的测试表明此代码给出了“未捕获的引用错误:赋值中的左侧无效”。在 Google Chrome 版本 24.0.1312.57 m 使用的任何版本的 JavaScript(“.js”)中。

这是 ES6 提案的一部分:它还没有正式化,因此不应该绝对假设它在任何地方都可以工作(如果可以,那就太棒了......)。
2021-03-22 21:07:45
它已在 es6 中标准化,此功能称为解构。
2021-03-22 21:07:45
它适用于 Chrome 版本 54.0.2840.71 及更早的版本。此外,如果您使用诸如babel 之类的 ES6 转译器,这应该是您的必备代码
2021-03-24 21:07:45
它适用于当前的 Firefox 最新版本 (39.0.3)。
2021-03-28 21:07:45
喜欢这个解决方案。清洁,如预期。太糟糕了,这个问题是 9 年前提出的...
2021-03-31 21:07:45

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

var tmp = list[x];
list[x] = list[y];
list[y] = tmp;
@ofir_aghai 是的,你是对的:10 多年前,另一个答案在这个答案之前22 秒发布(12:14:16Z vs 12:14:38Z)......
2021-03-16 21:07:45
你的“tmp”听起来比“b”更合理
2021-03-24 21:07:45
抱歉,它不允许我更改投票..“除非编辑此答案,否则您的投票现在已锁定”
2021-03-26 21:07:45
在平常的日子里,我一直坚持下去。但仅仅因为秒的问题和对你 10 年的尊重在这里恢复 ;-)
2021-03-30 21:07:45