数组过滤和对象转换:什么是最快的以及其他什么因素很重要?

时间:2017-07-28 09:57:21

标签: javascript arrays performance

假设我需要将数组转换为对象,并在此过程中进行一些过滤。

我有两种方法,一种是可链接的功能方法,例如.map.filter.reduce,另一种方法是使用旧学校for-loop循环数组。改变一个对象。

功能方式:

const output = fields
    .filter(field => field.required)
    .map(field => field.name)
    .reduce((acc, cur, i) => {
      acc[cur] = false;
      return acc;
    }, {});

旧学校for-loop方式:

let output2 = {};
for (var i = 0; i < fields.length; i++) {
  if (fields[i].required) {
    output2[fields[i].name] = false;
  }
}

我更喜欢功能方法,因为我认为它会带来更好的可读代码。然而,我很惊讶(并且有点失望)学习功能方法始终比非功能性的旧学校for-loop转换方式慢。请找the JSBench here

我认为这里可能有几件事情:

  1. 我是个白痴,我的实施存在缺陷,可以进行优化。
  2. &#34; JSBench不是衡量绩效的最佳方式。工具X,Y,Z是一种更好的衡量绩效的方法&#34;
  3. &#34;使用功能方法的性能损失是值得的,因为您可以使用const,其具有其他有益的方面,例如(半)不变性。&#34;
  4. 有人想要权衡吗?

    您可以在JSBench链接中找到我使用的测试数组。

3 个答案:

答案 0 :(得分:4)

&#34;过滤地图缩减&#34;循环3次相同的数组。 所以一个for循环总是更快。 但减少自己的工作很好

    const output = fields
    .reduce((acc, cur, i) => {
      if(cur.required){
        acc[cur.name] = false;
      }
      return acc;
    }, {});

答案 1 :(得分:1)

另一种功能方式,可能快三倍:

const output = fields
.reduce((acc, cur) => {
  if(curr.required) acc[cur.name] = false;
  return acc;
}, {});

你也可以使用Map(稍后会有更好的表现):

const output=new Map(fields.map(el=>el.required?[el.name,false]:[0,false]));
output.delete(0);

答案 2 :(得分:0)

您可以考虑将Object.assignArray#mapspread syntax ...结合使用。

const output = Object.assign({}, ...fields.map(o => (o.required && { [o.name]: false })));