繁体   English   中英

用唯一键将对象数组转换为对象的最有效方法是什么

[英]What is the most performant way to convert an Array of Object to an Object with unique keys

我试图找出最高性能的Javascript方法,将对象数组转换为具有唯一键的对象,并使用充满对象的数组作为值。

例如:

const array = [
  { "name": "greg", "year": "2000" },
  { "name": "john", "year": "2002" },
  { "name": "bob",  "year": "2005" },
  { "name": "ned",  "year": "2000" },
  { "name": "pam",  "year": "2000" },
];

我希望将其转换为:

{
  "2000": [ 
    { "name": "greg", "year": "2000" }, 
    { "name": "ned",  "year": "2000" },
    { "name": "pam",  "year": "2000" }
  ],
  "2002": [ { "name": "john", "year": "2002" } ],
  "2005": [ { "name": "bob",  "year": "2005" } ],
}

到目前为止,这是我到目前为止所做的:

let yearsObj = {};

for (let i=0; i<array.length; i++) {
  if (!yearsObj[array[i].year]) {
    yearsObj[array[i].year] = [];
  }

  yearsObj[array[i].year].push(array[i]);
}

您可以通过使用数组的reduce函数,以更优雅的方式实现此目的

// # impl


const group = key => array =>
  array.reduce(
    (objectsByKeyValue, obj) => ({
      ...objectsByKeyValue,
      [obj[key]]: (objectsByKeyValue[obj[key]] || []).concat(obj)
    }),
    {}
  );

// # usage 

console.log(
  JSON.stringify({
    byYear: group(array),
  }, null, 1)
);

//输出

VM278:1 {“ carsByBrand”:{“ 2000”:[{“ name”:“ greg”,“ year”:“ 2000”},{“ name”:“ ned”,“ year”:“ 2000”}, {“ name”:“ pam”,“ year”:“ 2000”}],“ 2002”:[{“ name”:“ john”,“ year”:“ 2002”}],“ 2005”:[{“名称”:“鲍勃”,“年份”:“ 2005”}}}}

它可能就像Object.fromEntries(array.map(obj => [obj.year,obj]))一样简单,即使它不是您所需要的,但是谈论性能却比所有建议的都要慢,所以我给出了一个不好的例子,表明简短的陈述并非总是最快的。 您的方式似乎是最快的性能。 运行下面的代码片段以查看实际时间。

 // common let array = [ { "name": "greg", "year": "2000" }, { "name": "john", "year": "2002" }, { "name": "bob", "year": "2005" }, { "name": "ned", "year": "2000" }, { "name": "pam", "year": "2000" }, ]; // simple as a statement way console.time(); console.log(Object.fromEntries(array.map(obj => [obj.year,obj]))); console.timeEnd(); // using .reduce way console.time(); const result = array.reduce((prev, curr) => { const { year } = curr; if (prev[year]) { prev[year].push(curr); } else { prev[year] = [curr]; } return prev; }, {}); console.log(result); console.timeEnd(); // your way console.time(); let yearsObj = {}; for (let i=0; i<array.length; i++) { if (!yearsObj[array[i].year]) { yearsObj[array[i].year] = []; } yearsObj[array[i].year].push(array[i]); } console.log(yearsObj); console.timeEnd(); 

在大多数情况下,像您这样的for循环(命令式)可能是最快的。 但是,在这种情况下,您不太可能看到很大的不同。 您可以在示例中改善代码的一件事是在for循环之前获取数组长度并将其分配给变量,这样就不必在每次循环迭代时都计算出数组长度。

const yearsObj = {};
const arrayLength = array.length; // Only calculate array length once

for (let i=0; i<arrayLength; i++) {
  if (!yearsObj[array[i].year]) {
    yearsObj[array[i].year] = [];
  }

  yearsObj[array[i].year].push(array[i]);
}

在这种情况下,我的首选是使用Array.reduce() 它更具可读性,并且性能差异可以忽略不计。

const arr = [
  { name: 'greg', year: '2000' },
  { name: 'john', year: '2002' },
  { name: 'bob', year: '2005' },
  { name: 'ned', year: '2000' },
  { name: 'pam', year: '2000' },
];

const result = arr.reduce((prev, curr) => {
  const { year } = curr;
  if (prev[year]) {
    prev[year].push(curr);
  } else {
    prev[year] = [curr];
  }
  return prev;
}, {});

/* Result:
{ '2000': 
   [ { name: 'greg', year: '2000' },
     { name: 'ned', year: '2000' },
     { name: 'pam', year: '2000' } ],
  '2002': [ { name: 'john', year: '2002' } ],
  '2005': [ { name: 'bob', year: '2005' } ] }
*/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM