Сократить быстрее, чем фильтр + карта в целом? - PullRequest
0 голосов
/ 19 ноября 2018

Вдохновленный этим вопросом:

замените фильтр и сопоставьте с уменьшением es6

Я решил проверить, быстрее ли reduce чем filter плюс 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();
<div>Filter plus map: <span id='filterPlusMap'></span> milliseconds</div>
<div>Reduce: <span id='reduce'></span> milliseconds</div>

и оказалось, что reduce как в 100 раз хуже ...

Но потом я изменил метод назначения в 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();
<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, а не фильтр + карта?

1 Ответ

0 голосов
/ 19 ноября 2018

Объясните, почему он так сильно изменился между скрипками?Т.е. - почему (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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...