2012-03-06 101 views
87

假設我想要一個返回輸入數組的排序副本的排序函數。我天真地嘗試這樣如何排序數組而不改變原始數組?

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); 
} 

,但它並不在所有的工作。

有沒有解決這個一個簡單的方法,prefereably不需要手卷我自己的排序算法或陣列中的每個元素複製到一個新的方式?

+0

創建數組的深層副本並對其進行排序。 – evanmcdonnal 2012-03-06 22:12:59

+0

@evanmcdonnal如果所有的想要的都是重新排序而不是數組中每個項目的重複,那麼淺拷貝可能就足夠了。 – Kekoa 2012-03-06 22:14:54

+0

'.sort'需要'this'值是數組,所以在過去的片斷工作,你會怎麼做'.sort.call(ARR)'(儘管它不能解決你的問題)。 – pimvdb 2012-03-06 22:15:19

回答

101

僅複製的陣列。有很多方法可以做到這一點:

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

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

這是否會進行深層複製,即嵌套的對象和數組是否也會被複制? – 2012-03-06 22:15:09

+0

用'concat'說'slice(0)'還有什麼好處嗎?或者它們幾乎都是一樣的嗎? – JaredPar 2012-03-06 22:15:21

+0

@JaredPar結果相同。如果你真的在微觀表現之後,你可以在http://jsperf.com/ – 2012-03-06 22:18:11

32

請嘗試以下

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

slice(0)表達創建數組的一個副本開始元素0

+18

+1,'.slice()'也適用。 – pimvdb 2012-03-06 22:16:21

16

您可以使用片不帶參數複製的數組:

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

不會複製給我 – Rbjz 2016-03-23 18:33:30

+2

@ RobertCutajar-Robajz,將該片段原樣複製到您的開發控制檯中,它會工作得很好。如果您遇到問題,則不在此答案中的代碼中。 – zzzzBov 2016-03-23 19:37:53

+0

是的,我有一個腳本緩存。有用。 – Rbjz 2016-03-24 08:24:44

-1

我用Object.assign()我的大多數副本:

var copyArray = Object.assign([], originalArray).sort(); 

然而,通過OP評論看後,我研究了一下深拷貝和原來Object.assign不僅執行淺拷貝,也只有選擇可枚舉和自己的屬性(如在this post中回答)。對於非深拷貝

0

你也可以做到這一點

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

這種方式不會變異。

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

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