一般而言,减少速度快于filter + map吗?

时间:2018-11-19 13:34:12

标签: javascript ecmascript-6

受到这个问题的启发:

replace filter and map with reduce es6

在给定的示例中,我决定测试reduce是否比filtermap快。

我做了一个小提琴:

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();
<div>Filter plus map: <span id='filterPlusMap'></span> milliseconds</div>
<div>Reduce: <span id='reduce'></span> milliseconds</div>

结果发现reduce的情况要差100倍...

但是后来我在reduce中更改了分配方法,结果证明它比下一个小提琴中的filter + map更好(好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();
<div>Filter plus map: <span id='filterPlusMap'></span> milliseconds</div>
<div>Reduce: <span id='reduce'></span> milliseconds</div>

有人可以吗?

  1. 解释为什么小提琴之间的变化如此之大?即-为什么(prev.push(curr.val), prev)好得多?并且应该使用它吗?
  2. 告诉reduce是否始终比filter + map更受欢迎 ?

1 个答案:

答案 0 :(得分:5)

  

解释为什么小提琴之间的变化如此之大?即-为什么(prev.push(curr.val), prev)好得多?并且应该使用它吗?

(arr.push(val), val)[...arr, val]快得多,因为后者会将整个arr数组复制到一个新数组中,从而使reduce操作具有 O(n²) 时间复杂度。第一个只需向现有arr中添加1个元素,...这给整个reduce操作带来了 O(n)时间复杂度。

  

告诉reduce是否总是比filter + map更受青睐吗?

不,这实际上取决于要应用的逻辑以及对性能的要求。可读性也很重要:filtermapreduce更具可读性(可理解)。