如何在不改变原始数组的情况下对数组进行排序?

Pet*_*son 194 javascript

假设我想要一个返回输入数组的排序副本的sort函数.我天真地试过这个

function sort(arr) {
  return arr.sort();
}
Run Code Online (Sandbox Code Playgroud)

我用它测试了它,这表明我的sort方法正在改变数组.

var a = [2,3,7,5,3,7,1,3,4];
sort(a);
alert(a);  //alerts "1,2,3,3,3,4,5,7,7"
Run Code Online (Sandbox Code Playgroud)

我也试过这种方法

function sort(arr) {
  return Array.prototype.sort(arr);
}
Run Code Online (Sandbox Code Playgroud)

但它根本不起作用.

有没有一种简单的方法,优选的方式是不需要手动滚动我自己的排序算法或将数组的每个元素复制到一个新的元素?

Rob*_*b W 202

只需复制数组.有很多方法可以做到这一点:

function sort(arr) {
  return arr.concat().sort();
}

// Or:
return Array.prototype.slice.call(arr).sort(); // For array-like objects
Run Code Online (Sandbox Code Playgroud)

  • 现在报告切片速度明显更快 (9认同)
  • 为什么使用 `Array.prototype.slice.call(arr).sort();` 而不是 `arr.slice().sort();` ? (4认同)
  • @PeterOlson不,这是一个浅薄的副本.如果您确实需要深层复制,请使用Stack Overflow上的搜索功能查找现有的优秀答案. (3认同)
  • @OlivierBoissé 原型调用也适用于类似数组的对象。不仅仅是数组本身。 (3认同)
  • 这会进行深层复制吗,即是否也会复制嵌套的对象和数组? (2认同)
  • 使用 `concat` 比使用 `slice(0)` 有什么优势,或者它们几乎都一样? (2认同)
  • 正如下面提出的一些答案,你也可以使用 `Array.from`,我觉得它更具表现力:`Array.from(arr).sort()` 使用 `slice` 和 `concat`,我找到了数组重复性不那么明显。 (2认同)

Put*_*San 115

es6的另一种方式(非深拷贝):

const sorted = [...arr].sort();
Run Code Online (Sandbox Code Playgroud)

spread-syntax as array literal(从mdn复制):

var arr = [1, 2, 3];
var arr2 = [...arr]; // like arr.slice()
Run Code Online (Sandbox Code Playgroud)

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator

  • 对于那些说它不是有效 JavaScript 的人来说……它是完全有效的。如果您使用的是 Chrome/Safari/Edge 或 Firefox:打开开发控制台,定义一个名为“arr”的数组并粘贴表达式以查看结果。 (6认同)
  • @Cerin 听起来你使用的是一个非常过时的 JS 版本。 (3认同)

Jar*_*Par 57

请尝试以下方法

function sortCopy(arr) { 
  return arr.slice(0).sort();
}
Run Code Online (Sandbox Code Playgroud)

slice(0)表达式从元素0开始创建数组的副本.


zzz*_*Bov 30

您可以使用不带参数的slice来复制数组:

var foo,
    bar;
foo = [3,1,2];
bar = foo.slice().sort();
Run Code Online (Sandbox Code Playgroud)


Ran*_*ner 15

更新-Array.prototype.toSorted()提案

Array.prototype.toSorted(compareFn) -> Array是一种新方法,建议添加到该方法中Array.prototype,目前处于第 3 阶段(即将推出)。

此方法将保持目标数组不变,并返回执行更改的副本。


小智 11

ES2023 数组方法toSorted()

toSorted()实例的方法是Array该方法的复制sort()版本。它返回一个新数组,其中元素按升序排序。

const arr = [2, 1, 3];
const arrSorted = arr.toSorted();
console.log(arr); //[2, 1, 3]
console.log(arrSorted); //[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)


小智 8

您也可以这样做

d = [20, 30, 10]
e = Array.from(d)
e.sort()
Run Code Online (Sandbox Code Playgroud)

这样d将不会被突变。

function sorted(arr) {
  temp = Array.from(arr)
  return temp.sort()
}

//Use it like this
x = [20, 10, 100]
console.log(sorted(x))
Run Code Online (Sandbox Code Playgroud)