如何通过ID简洁地分布对象数组?

时间:2019-04-09 22:59:59

标签: javascript ecmascript-6 iteration

我有一系列物品:

const arr = [
  { id: 'abc', value: 2 },
  { id: 'def', value: 3 },
];

我想通过id创建一个物品对象:

const obj = {
  abc: { id: 'abc', value: 2 },
  def: { id: 'def', value: 3 },
};

据我所知,最高效,最简洁的方法是通过Array.prototype.reduce

const obj = arr.reduce((obj, entry) => {
  obj[entry.id] = entry;
  return obj;
}, {});

是否有性能更高更简洁的操作方法?他们是什么?

我知道这是相对主观的,因此我乐意接受一些建议,让我可以更好地表达问题。谢谢。

1 个答案:

答案 0 :(得分:3)

您可以使用comma operator将其设置为单线:

const arr = [
  { id: 'abc', value: 2 },
  { id: 'def', value: 3 },
];

const obj = arr.reduce((obj, entry) => (obj[entry.id] = entry, obj), {});

console.log(obj);

可读性较差,但更为简洁。是否值得,取决于您。既然您提到您对spread感兴趣,这就是该解决方案,但是请参见下文以了解性能:

const arr = [
  { id: 'abc', value: 2 },
  { id: 'def', value: 3 },
];

const obj = arr.reduce((obj, entry) => ({ ...obj, [entry.id]: entry }), {});

console.log(obj);

另一种使用通过Object.assign进行参数扩展的解决方案,但是这段代码对我来说有点笨拙,有关性能,请参见下文:

const arr = [
  { id: 'abc', value: 2 },
  { id: 'def', value: 3 },
];

const obj = Object.assign({}, ...arr.map(a => ({ [a.id]: a })));

console.log(obj);


对于性能最高的解决方案,很难克服for循环:

const arr = [
  { id: 'abc', value: 2 },
  { id: 'def', value: 3 },
];

const obj = {}, len = arr.length;
for(let i = 0; i < len; i++) {
  let a = arr[i];
  obj[a.id] = a;
}

console.log(obj);

在我的计算机上进行的快速基准测试得出以下结果(在Firefox 66上):

test case     | ops/s             | result
reduce-comma  | 22,248,622 ±2.83% |  6.89% slower
reduce-spread |  4,149,590 ±2.84% | 82.63% slower
object-assign |  1,809,170 ±0.69% | 92.43% slower
for-loop      | 23,895,193 ±2.51% | fastest

第二个解决方案由于使用对象散布运算符而变得慢得多,该操作会在每次迭代时克隆对象。老实说,我不确定为什么Object.assign会更慢,因为大多数对象传播的实现都只是Object.assign的掩饰。

最后两个选项之间的区别是 miniscule ,但在优化效果欠佳的旧版浏览器中,差异可能更大。如果这确实是对性能至关重要的应用程序,我建议您运行自己的基准测试。