2016-08-13 24 views
0

考慮我們有2個大小爲N和M非常大的陣列,的Javascript推到數組 - 性能

var array1 = [1,2,3...N], 
    array2 = [a,b,c...M]; 

什麼是推到數組2的陣列1的最優化的方式?

使用原生的JavaScript,

Array.prototype.push.apply(array1,array2) 

使用Lodash,

array1 = _.concat(array1, array2) 

由於lodash使得源陣列的複製,我想這是複雜將由O(N)作爲比較本地JavaScript增加。 有沒有其他優化的方式來推動數組? 另外,爲什麼像lodash這樣一個非常流行的庫不能提供修改現有數組以提高性能的選項?

+0

至於lodash的功能,我懷疑'_.concat'不修改現有的陣列,因爲.concat'沒有任何本地'。 –

+0

(偏離主題),但爲什麼你甚至會考慮對數組實例上的'Array.prototype.push.apply(array1,array2)'進行操作?,只有在需要「借用」時才使用調用或綁定或應用函數「一個來自Array.prototype對象的函數來調用**類似**的對象,比如'arguments'。只需做'array1.concat(array2)' – Dummy

+1

@Dummy concat創建源數組的副本,push不會創建任何副本並修改現有數組,因此push的性能應該更好。 – Ankush

回答

1

讓我們做一個簡單的測試,看看。當數組作爲參數應用推送時,大到150K(在我目前的情況下它發生在250076以上),你會注意到我在評論中提到的範圍錯誤。這是一個主要問題,因爲對於較小的陣列,性能差異無論如何都可忽略不計。因此,如果要連接的數組的大小足以讓您關注操作的性能,那麼應該避免在應用程序或擴展操作符中使用push。

function measureConcatPerformances() { 
 
    var len = +arrayLength.value, 
 
    ar1 = new Array(len).fill().map(e => ~~(Math.random() * 1000000)), 
 
    ar2 = new Array(len).fill().map(e => ~~(Math.random() * 1000000)), 
 
    ts = 0, 
 
    te = 0; 
 
    
 
    myError.textContent = ""; 
 
    ts = performance.now(); 
 
    for (var i = 0; i < len; i++) ar1[ar1.length] = ar2[i]; 
 
    te = performance.now(); 
 
    forLoopResult.textContent = "ar1 and ar2 concataned in: " + (te - ts) + "msec by for loop"; 
 

 
    ar1 = new Array(len).fill().map(e => ~~(Math.random() * 1000000)); 
 
    ar2 = new Array(len).fill().map(e => ~~(Math.random() * 1000000)); 
 

 
    ts = performance.now(); 
 
    for (var val of ar2) ar1[ar1.length] = val; 
 
    te = performance.now(); 
 
    forOfResult.textContent = "ar1 and ar2 concataned in: " + (te - ts) + "msec by for of loop"; 
 

 
    ar1 = new Array(len).fill().map(e => ~~(Math.random() * 1000000)); 
 
    ar2 = new Array(len).fill().map(e => ~~(Math.random() * 1000000)); 
 
    try{ 
 
    ts = performance.now(); 
 
    Array.prototype.push.apply(ar1, ar2); 
 
    te = performance.now(); 
 
    applyResult.textContent = "ar1 and ar2 concataned in: " + (te - ts) + "msec by apply"; 
 
    } catch(err) {myError.textContent = "Error at apply: " + err} 
 
    
 
    ar1 = new Array(len).fill().map(e => ~~(Math.random() * 1000000)); 
 
    ar2 = new Array(len).fill().map(e => ~~(Math.random() * 1000000)); 
 

 
    ts = performance.now(); 
 
    ar1 = ar1.concat(ar2); 
 
    te = performance.now(); 
 
    concatResult.textContent = "ar1 and ar2 concataned in: " + (te - ts) + "msec by concat"; 
 
} 
 

 
myButton.addEventListener("click", measureConcatPerformances);
<input id="arrayLength" type="number" min="0" value = 0> 
 
<button id="myButton">Length</button> 
 
    <p id="forLoopResult"></p> 
 
    <p id="forOfResult"></p> 
 
    <p id="applyResult"></p> 
 
    <p id="concatResult"></p> 
 
    <p id="myError" style="color:red"></p>

0

您可以使用rest element將數組元素收集到另一個數組中;這是集array2array1時創建兩個數組

var array1 = [...[1,2,3] ...(array2 = ["a", "b", "c"])]; 
1

push.apply(array1, array2)是最理想的,因爲它修改的array1的參考,但不能複製/它返回到重新分配。