假设我想要一个排序函数,它返回输入数组的排序副本。我天真地尝试了这个
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);
}
但它根本不起作用。
有没有一种直接的方法来解决这个问题,最好是一种不需要手动滚动我自己的排序算法或将数组的每个元素复制到新元素中的方法?
.sort
要求 this
值是数组,因此要使最后一个代码段起作用,您需要执行 .sort.call(arr)
(尽管它不能解决您的问题)。
您需要先复制数组,然后再对其进行排序。 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
只需复制数组。有很多方法可以做到这一点:
function sort(arr) {
return arr.concat().sort();
}
// Or:
return Array.prototype.slice.call(arr).sort(); // For array-like objects
concat
比使用 slice(0)
有什么优势,还是它们几乎都一样?
Array.prototype.slice.call(arr).sort();
而不是 arr.slice().sort();
?
尝试以下
function sortCopy(arr) {
return arr.slice(0).sort();
}
slice(0)
表达式创建从元素 0 开始的数组副本。
您可以使用不带参数的 slice 来复制数组:
var foo,
bar;
foo = [3,1,2];
bar = foo.slice().sort();
你也可以这样做
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)
请注意:对于非常大的阵列,这可能会很慢。
-
而不是 >
。
更新 - Array.prototype.toSorted()
个提案
Array.prototype.toSorted(compareFn) -> Array
是一种建议添加到 Array.prototype
的方法,目前在 stage 3 中(即将可用)。
此方法将保持目标 Array 不变,并返回它的副本并执行更改。
试试这个对数字进行排序。这不会改变原始数组。
function sort(arr) {
return arr.slice(0).sort((a,b) => a-b);
}
有一个新的 tc39 proposal,它向 Array
添加了一个 toSorted
方法,该方法返回数组的副本并且不修改原始数组。
例如:
const sequence = [3, 2, 1];
sequence.toSorted(); // => [1, 2, 3]
sequence; // => [3, 2, 1]
由于它目前处于第 3 阶段,它可能很快会在浏览器引擎中实现,但与此同时,可以在 here 或 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;
};
}
这种解决问题的方法在我的情况下是理想的。
arr
的数组并粘贴表达式以查看结果。.slice()
更快地获取数组的副本?