如何对数组进行排序而不改变原始数组?

让我们假设我想要一个排序函数,它返回输入数组的排序副本。我很天真地试过

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

并且我用这个测试了它,这表明我的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"

我也尝试过这种方法

function sort(arr) {
return Array.prototype.sort(arr);
}

但它根本不起作用。

有没有一种直接的方法来解决这个问题,最好是一种不需要手动滚动我自己的排序算法或将数组中的每个元素复制到一个新的数组中的方法?

197087 次浏览

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

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


// Or:
return Array.prototype.slice.call(arr).sort(); // For array-like objects

试试下面的方法

function sortCopy(arr) {
return arr.slice(0).sort();
}

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

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

var foo,
bar;
foo = [3,1,2];
bar = foo.slice().sort();

在对数组排序之前,需要复制它。使用es6的一种方法:

const sorted = [...arr].sort();

扩展语法作为数组文字(复制自mdn):

var arr = [1, 2, 3];
var arr2 = [...arr]; // like arr.slice()

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

你也可以这样做

d = [20, 30, 10]
e = Array.from(d)
e.sort()

这样d就不会发生突变。

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


//Use it like this
x = [20, 10, 100]
console.log(sorted(x))

任何想要做深度复制的人(例如,如果你的数组包含对象)可以使用:

let arrCopy = JSON.parse(JSON.stringify(arr))

然后你可以在不改变arr的情况下对arrCopy进行排序。

arrCopy.sort((obj1, obj2) => obj1.id > obj2.id)

请注意:对于非常大的数组,这可能会很慢

试试这个来排序数字。这不会改变原始数组。

function sort(arr) {
return arr.slice(0).sort((a,b) => a-b);
}

有一个新的tc39提议,它向Array添加了一个toSorted方法,该方法返回数组的副本,并且不修改原始数组。

例如:

const sequence = [3, 2, 1];
sequence.toSorted(); // => [1, 2, 3]
sequence; // => [3, 2, 1]

由于它目前处于第3阶段,可能很快就会在浏览器引擎中实现,但与此同时,在在这里core-js中可以使用polyfill。

我认为我的回答有点晚了,但如果有人再次遇到这个问题,解决方案可能是有用的。

我还可以用本地函数返回一个已排序的数组提出另一种方法。

此代码仍然变异是原始对象,但不是本机行为,此实现返回一个已排序的数组。

// Remember that it is not recommended to extend build-in prototypes
// or even worse override native functions.
// You can create a seperate function if you like


// You can specify any name instead of "sorted" (Python-like)


// Check for existence of the method in prototype
if (typeof Array.prototype.sorted == "undefined") {
// If it does not exist you provide your own method
Array.prototype.sorted = function () {
Array.prototype.sort.apply(this, arguments);
return this;
};
}

这种解决问题的方法在我的情况下是理想的。

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

Array.prototype.toSorted(compareFn) -> Array是一个被提议添加到Array.prototype中的方法,目前在第三阶段中(即将可用)。

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