如何在不改变原始数组的情况下对数组进行排序?
如何在不改变原始数组的情况下对数组进行排序?
假设我想要一个返回已排序副本的排序函数。我尝试了以下代码:\n
function sort(arr) { return arr.sort(); }
\n并且我用以下测试代码进行了测试,结果显示我的`sort`方法改变了原数组。\n
var a = [2,3,7,5,3,7,1,3,4]; sort(a); alert(a); //弹出"1,2,3,3,3,4,5,7,7"
\n我还尝试了以下方法:\n
function sort(arr) { return Array.prototype.sort(arr); }
\n但是它根本不起作用。\n有没有一种简单直接的方法来解决这个问题,最好不需要手动编写自己的排序算法或将数组的每个元素复制到一个新数组中?
我们经常需要对数组进行排序操作,但有时候我们又不希望改变原始数组的顺序。那么如何在不改变原始数组的情况下对数组进行排序呢?
一个解决方法是使用slice(0)
方法来创建原始数组的副本,然后对副本进行排序操作。这样就可以保持原始数组的顺序不变。
下面是一个示例代码:
function sortCopy(arr) { return arr.slice(0).sort(); }
在这个代码中,slice(0)
方法创建了一个从第一个元素开始的数组副本。然后,sort()
方法对副本进行排序操作。最后,返回排序后的副本数组。
这种方法的原理是,slice(0)
方法会返回一个新的数组,其中包含原始数组的所有元素。由于我们对副本数组进行排序操作,所以原始数组的顺序不会受到影响。
使用这种方法,我们可以在不改变原始数组的情况下对数组进行排序。这对于某些特定的应用场景非常有用,例如需要保留原始数组的顺序,同时又需要对数组进行排序。
总结起来,通过使用slice(0)
方法创建原始数组的副本,我们可以在不改变原始数组的情况下对数组进行排序。这种方法非常简单有效,并且可以帮助我们解决这个问题。
如何在不改变原始数组的情况下对数组进行排序?
有很多方法可以实现这一点:
function sort(arr) { return arr.concat().sort(); } // 或者: return Array.prototype.slice.call(arr).sort(); // 适用于类数组对象
这样做会进行深拷贝吗?嵌套的对象和数组会被拷贝吗?
不,这只是进行浅拷贝。如果你真的想要进行深拷贝,可以使用 Stack Overflow 上的搜索功能,找到现有的优秀答案。
使用`concat`相对于`slice(0)`有什么优势吗?它们基本上都是一样的吗?
结果是相同的。如果你真的关注微小的性能差异,你可以在[jsperf.com](http://jsperf.com/)上设置(或查找)一个性能检查。
不是很关心微小的性能。我之前看到的所有示例都使用了`slice`,我想知道是否有某种固有的理由更喜欢`concat`。
像下面几个答案中提到的那样,你也可以使用`Array.from`,我觉得这种方式更加表达清晰:`Array.from(arr).sort()`。对于`slice`和`concat`,我发现数组复制的意图不太明显。
为什么要使用`Array.prototype.slice.call(arr).sort();`而不是`arr.slice().sort();`?
原型调用也适用于类数组对象,而不仅仅是数组本身。
要在不改变原始数组的情况下对数组进行排序,可以使用`concat`或`Array.prototype.slice.call`方法来复制数组。这些方法只会进行浅拷贝,如果需要进行深拷贝,可以在 Stack Overflow 上搜索相关答案。此外,还可以使用`Array.from`方法来复制数组,并对复制后的数组进行排序。这些方法在性能方面可能存在微小差异,可以在[jsperf.com](http://jsperf.com/)上进行性能测试。最重要的是,不要复制粘贴代码,要选择一个在npm包中的解决方案。
如何在不改变原始数组的情况下对数组进行排序?
有时候我们需要对数组进行排序,但又不希望改变原始数组的顺序。这种情况下,我们需要先复制数组,然后对复制后的数组进行排序。
在ES6中,可以使用扩展运算符来复制数组。具体代码如下:
const sorted = [...arr].sort();
这里的`[...arr]`表示将原数组`arr`展开成一个新的数组,相当于使用`arr.slice()`来复制数组。
这种方法非常简洁易懂,比使用`concat`等其他方法更容易理解。
不过需要注意的是,有些开发者在使用这种方法时可能会遇到语法错误。例如在使用Gulp编译JS代码时可能会出现`SyntaxError: Unexpected token: punc (.)`的错误。
但实际上,这种写法是完全有效的JavaScript代码。如果你使用的是Chrome/Safari/Edge或Firefox浏览器,可以打开开发者控制台,定义一个名为`arr`的数组,并将上述代码粘贴进去,就可以看到结果。
有人可能会问,这种方法和使用`.slice()`来复制数组相比,哪个更快?
对于简单的数组结构来说,这种方法可能确实更快。但对于更复杂的数据结构,浅拷贝可能就不够了。这时候可以使用类似下面的方法来进行深拷贝:
let arr2 = JSON.parse(JSON.stringify(arr));
需要注意的是,对于排序操作来说,原始对象的顺序是可以改变的。只有当对对象进行了之后的修改时,才可能出现问题。
我们可以利用ES6的扩展运算符来复制数组,然后对复制后的数组进行排序,从而实现在不改变原始数组的情况下对数组进行排序的目的。对于更复杂的数据结构,可以使用深拷贝的方式来复制数组。