考虑我们有2个非常大的大小为N和M的数组,
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制作源数组的副本,我猜它的复杂性会因为与原生javascript相比增加O(N)。 推送阵列还有其他优化的方法吗? 另外,为什么像lodash这样极受欢迎的库不能提供修改现有阵列以提高性能的选项?
答案 0 :(得分:1)
push.apply(array1, array2)
是最优的,因为它修改了array1
的引用,但没有复制/返回它以重新分配。
答案 1 :(得分:1)
让我们做一个简单的测试,看看。当数组通过apply作为参数传递给push时,大小就像150K(在我目前的情况下它发生在250076之后),你会注意到我在评论中提到的范围错误。这是一个主要问题,因为对于较小的阵列,性能差异无论如何都可以忽略不计。因此,如果要连接的数组足以让您关注操作的性能,则应避免使用push with 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>
答案 2 :(得分:0)
您可以使用rest element
将数组元素收集到另一个数组中;在创建两个数组时将array2
收集到array1
var array1 = [...[1,2,3] ...(array2 = ["a", "b", "c"])];