2016-08-13 3 views
0

Рассмотрим мы имеем 2 очень большие массивы размера N и M,Javascript толчок в массив - Performance

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

Какой самый оптимизированный способ толкания array2 в array1?

Использование родной JavaScript,

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

Использование Lodash,

array1 = _.concat(array1, array2) 

Как lodash делает копию исходного массива, я предполагаю, что сложность увеличится на O (N), как по сравнению с родной JavaScript. Есть ли другой оптимизированный способ push массива? Кроме того, почему очень популярная библиотека, например, 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 с оператором apply или spread, если ваш массив, который будет конкатенирован, достаточно велик, чтобы вы были обеспокоены эксплуатацией операции.

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 для сбора элементов массива в другой массив; что собирают array2 в array1, когда оба массива созданы

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

push.apply(array1, array2) является наиболее оптимальным, поскольку он изменяет ссылку на array1, но не копировать/вернуть его можно переназначить.