一般来说,减少比过滤器+地图更快吗?

pbi*_*aly 1 javascript ecmascript-6

灵感来自这个问题:

用reduce es6替换filter和map

在给定的例子中,我决定测试是否reducefilterplus 更快map.

我做了一个小提琴:

var data = Array(10 ** 4).fill(null).map((_, i) => {
  return {
    checked: Math.random() < 0.5,
    val: Math.floor(Math.random() * 10000)
  }
})

f1 = () => {
  t0 = performance.now();
  data.filter(el => el.checked).map(el => el.val)
  t1 = performance.now();
  // console.log("filter plus map took " + (t1 - t0) + " milliseconds.")
  document.getElementById('filterPlusMap').innerText = t1 - t0;
}

f2 = () => {
  t0 = performance.now();
  data.reduce((prev, curr) => {
    return curr.checked ? [...prev, curr.val] : prev 
  }, [])
  t1 = performance.now();
  // console.log("reduce took " + (t1 - t0) + " milliseconds.")
  document.getElementById('reduce').innerText = t1 - t0;
}

f1();
f2();
Run Code Online (Sandbox Code Playgroud)
<div>Filter plus map: <span id='filterPlusMap'></span> milliseconds</div>
<div>Reduce: <span id='reduce'></span> milliseconds</div>
Run Code Online (Sandbox Code Playgroud)

事实证明,这比reduce100倍差......

但后来我改变了赋值方法,reduce结果证明它比下一个小提琴中的滤镜+贴图更好(比4倍好):

var data = Array(10 ** 6).fill(null).map((_, i) => {
  return {
    checked: Math.random() < 0.5,
    val: Math.floor(Math.random() * 10000)
  }
})

f1 = () => {
  t0 = performance.now();
  data.filter(el => el.checked).map(el => el.val)
  t1 = performance.now();
  // console.log("filter plus map took " + (t1 - t0) + " milliseconds.")
  document.getElementById('filterPlusMap').innerText = t1 - t0;
}

f2 = () => {
  t0 = performance.now();
  data.reduce((prev, curr) => {
    return curr.checked ? (prev.push(curr.val), prev) : prev 
  }, [])
  t1 = performance.now();
  // console.log("reduce took " + (t1 - t0) + " milliseconds.")
  document.getElementById('reduce').innerText = t1 - t0;
}

f1();
f2();
Run Code Online (Sandbox Code Playgroud)
<div>Filter plus map: <span id='filterPlusMap'></span> milliseconds</div>
<div>Reduce: <span id='reduce'></span> milliseconds</div>
Run Code Online (Sandbox Code Playgroud)

有人可以请:

  1. 解释为什么它在小提琴之间发生了很大的变化?即 - 为什么(prev.push(curr.val), prev)好多了?它应该被使用吗?
  2. 告诉我是否reduce应该总是优先考虑过滤器+地图?

tri*_*cot 5

解释为什么它在小提琴之间发生了很大的变化?即 - 为什么(prev.push(curr.val), prev)好多了?它应该被使用吗?

(arr.push(val), val)[...arr, val]后者将整个arr阵列复制到一个新阵列要快得多,这使得reduce操作的时间复杂度为O(n²).第一个只需要向现有元素添加1个元素arr,...这给整个操作带来了O(n)时间复杂度reduce.

告诉我是否reduce应该总是优先选择filter+ map

不,这实际上取决于要应用的逻辑以及您在性能方面的要求.可读性也很重要:filter并且map往往比可读性更高(可理解)reduce.

  • 查找["逗号运算符"](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator). (2认同)
  • @pbialy 它被称为 [逗号运算符](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator) - 这就是你要问的吗? (2认同)