在JavaScript中交换数组元素

342
有没有一种更简单的方法来交换数组中的两个元素?
var a = list[x], b = list[y];
list[y] = a;
list[x] = b;

ES2023 数组方法 with() 可以在一行中完成:list.with(x,list[y]).with(y,list[x]) 看看我的答案和示例! - XMehdi01
ES2023 数组方法 with() 可以在一行中完成:list.with(x,list[y]).with(y,list[x]) 看看我的回答,附带一个示例! - undefined
36个回答

1
如果你不想在ES5中使用临时变量,这是一种交换数组元素的方法。
var swapArrayElements = function (a, x, y) {
  if (a.length === 1) 
    return a;
  a.splice(y, 1, a.splice(x, 1, a[y])[0]);
  return a;
};

swapArrayElements([1, 2, 3, 4, 5], 1, 3); //=> [ 1, 4, 3, 2, 5 ]

这种方式,你不需要创建一个临时变量,而是创造了两个新的数组,因为 a.splice 返回一个包含已删除元素的数组。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/splice - XCS
有没有更好的方法可以做到这一点?@Cristy - venkat7668
被接受的答案非常简单明了。当你有变量声明数量限制时,这将非常方便(主要用于面试 :))。但正如你所提到的那样,并不是内存效率高的做法。@Cristy - venkat7668
我个人认为这是一种不好的做法,不应该推荐给初学者。而且它也很难阅读。 - XCS

1
Array.prototype.swap = function(a, b) {
  var temp = this[a];
  this[a] = this[b];
  this[b] = temp;
};

使用方法:

var myArray = [0,1,2,3,4...];
myArray.swap(4,1);

1
不需要这么粗鲁。此外,扩展“Array”原型并不是要求的一部分 - 它可能会带来更多困惑而不是好处。 - Mathias Lykkegaard Lorenzen
3
你把它表达为“正确的方式”。这可能会给人留下错误的印象。相反,我建议提到你正在做什么(扩展原型),以及它如何有用,就像你刚刚对我所描述的那样。 - Mathias Lykkegaard Lorenzen
1
抓住你了,有时候我的姿态不太对,抱歉 ^_^ - Pryme8
那么也许考虑删除您的答案,或者遵循给出投票原因的人的建议。 - Mathias Lykkegaard Lorenzen
3
您是唯一一个在回答的背景下描述问题的人...首先,负分应该留给不起作用的答案。其次,这是一个好答案,使用优雅,不会引起冲突。评判代码而不是表述方式。此外,在我的答案中,如果您将其剥离并排除原型扩展,它就与得票最高的答案完全相同,因此,这个答案被投票降至-6表明了那些投票者缺乏思考。而且,这个答案是在得票最高的答案之前数月发布的...所以这听起来更像是一个流行度比代码竞赛。 - Pryme8
显示剩余2条评论

1
这里有一个变体,首先检查索引是否存在于数组中:
Array.prototype.swapItems = function(a, b){
    if(  !(a in this) || !(b in this) )
        return this;
    this[a] = this.splice(b, 1, this[a])[0];
    return this;
}

如果索引不存在,它目前只会返回this,但您可以轻松修改失败的行为。

1
一个 TypeScript 的解决方案,它会克隆数组而不是改变现有的数组:
export function swapItemsInArray<T>(items: T[], indexA: number, indexB: number): T[] {
  const itemA = items[indexA];

  const clone = [...items];

  clone[indexA] = clone[indexB];
  clone[indexB] = itemA;

  return clone;
}

1
如果由于某些原因您不允许使用就地交换,那么这里有一个使用map的解决方案:

function swapElements(array, source, dest) {
  return source === dest
? array : array.map((item, index) => index === source
  ? array[dest] : index === dest 
  ? array[source] : item);
}

const arr = ['a', 'b', 'c'];
const s1 = swapElements(arr, 0, 1);
console.log(s1[0] === 'b');
console.log(s1[1] === 'a');

const s2 = swapElements(arr, 2, 0);
console.log(s2[0] === 'c');
console.log(s2[2] === 'a');

以下是TypeScript代码,可供快速复制粘贴:

function swapElements(array: Array<any>, source: number, dest: number) {
  return source === dest
    ? array : array.map((item, index) => index === source
      ? array[dest] : index === dest 
      ? array[source] : item);
}

1
ES2023数组方法with()

Array实例的with()方法是使用方括号表示法更改给定索引值的复制版本。它返回一个新数组,其中给定索引处的元素被替换为给定的值。

const list = [1, 2, 3], x= 0, y= 1;
console.log(list.with(x,list[y]).with(y,list[x])); // [2, 1, 3]

PS:with()方法几乎被所有浏览器和 Node.js 版本 20+ 支持。
请见浏览器兼容性


0
为了简洁起见,这里提供一个丑陋的一行版本,仅比上面所有的连接和切片略好。被接受的答案确实是正确的方法,而且更易读。
给定:
var foo = [ 0, 1, 2, 3, 4, 5, 6 ];

如果你想交换两个索引(a和b)的值;那么这样做就可以了:
foo.splice( a, 1, foo.splice(b,1,foo[a])[0] );

例如,如果您想交换3和5,则可以这样做:
foo.splice( 3, 1, foo.splice(5,1,foo[3])[0] );

或者

foo.splice( 5, 1, foo.splice(3,1,foo[5])[0] );

两者产生相同的结果:

console.log( foo );
// => [ 0, 1, 2, 5, 4, 3, 6 ]

#splicehatersarepunks:)


0
在不使用临时变量或ES6交换方法[a, b] = [b, a]的情况下,交换数组中的第一个和最后一个元素:

[a.pop(), ...a.slice(1), a.shift()]


0
现场交换:
// Array methods
function swapInArray(arr, i1, i2){
    let t = arr[i1];
    arr[i1] = arr[i2];
    arr[i2] = t;
}

function moveBefore(arr, el){
    let ind = arr.indexOf(el);
    if(ind !== -1 && ind !== 0){
        swapInArray(arr, ind, ind - 1);
    }
}

function moveAfter(arr, el){
    let ind = arr.indexOf(el);
    if(ind !== -1 && ind !== arr.length - 1){
        swapInArray(arr, ind + 1, ind);
    }
}

// DOM methods
function swapInDom(parentNode, i1, i2){
    parentNode.insertBefore(parentNode.children[i1], parentNode.children[i2]);
}

function getDomIndex(el){
    for (let ii = 0; ii < el.parentNode.children.length; ii++){
        if(el.parentNode.children[ii] === el){
            return ii;
        }
    }
}

function moveForward(el){
    let ind = getDomIndex(el);
    if(ind !== -1 && ind !== 0){
        swapInDom(el.parentNode, ind, ind - 1);
    }
}

function moveBackward(el){
    let ind = getDomIndex(el);
    if(ind !== -1 && ind !== el.parentNode.children.length - 1){
        swapInDom(el.parentNode, ind + 1, ind);
    }
}

0
使用JavaScript ES6特性:

// Example 1: swapping array index

let arr = ["one", "two"];
[arr[0], arr[1]] = [arr[1], arr[0]];

// Output: arr = ["two", "one"]
console.log(arr);

// Example 2: swapping two variables value

let a = 10;
let b = 20;

[a, b] = [b, a];

// Output: a = 20, b = 10;

console.log(a, b);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接