【问题标题】:How to convert multiple objects in an array to a new object?如何将数组中的多个对象转换为新对象?
【发布时间】:2021-12-26 14:11:21
【问题描述】:

假设我在下面有一个数组:

[
  { type: 'senior', schoolName: 'school-A', country: 'America' },
  { type: 'senior', schoolName: 'school-B', country: 'England' },
  { type: 'junior', schoolName: 'school-C', country: 'German' },
  { type: 'junior', schoolName: 'school-D', country: 'Italy' }, 
]

如何将上面的数组转换为如下所示的对象:

{
  senior: {
    America: 'school-A', 
    England: 'school-B'
  }, 
  junior: {
    German: 'school-C', 
    Italy: 'school-D'
  }
}

在语法上最简洁的方法是什么?

感谢您的帮助!!

【问题讨论】:

  • 如果美国有两所高中呢?

标签: javascript node.js arrays object


【解决方案1】:

一种方法是将reduce 您的对象数组转换为单个对象。对于每次迭代,您可以累积您的对象(最初从一个空对象 {} 开始),以包含当前的 type 键以及国家和学校名称的新键值对。通过使用spread syntax ...,您可以将先前在type 键处看到的对象(来自您当前累积的对象)与您正在构建的新对象合并。

请参阅下面示例中的代码 cmets:

const arr = [ { type: 'senior', schoolName: 'school-A', country: 'America' }, { type: 'senior', schoolName: 'school-B', country: 'England' }, { type: 'junior', schoolName: 'school-C', country: 'German' }, { type: 'junior', schoolName: 'school-D', country: 'Italy' }, ];

const res = arr.reduce((acc, {type, schoolName, country}) => ({ // obtain the kys from the current object using destructuring assignment
  ...acc, // merge the current object stored in acc into the current object `{}` we're building
  [type]: { // using "computed property names"
    ...acc[type], // merge inner object (still worrks when acc[type] === undefined) 
    [country]: schoolName
  }
}), {}); // start with an initial empty object `{}` that we'll accumulate to
console.log(res);

每次迭代传播对象可能被视为效率低下,因此您可以累积单个对象引用(此时,为了提高可读性,可能值得考虑使用标准 for 循环):

const arr = [ { type: 'senior', schoolName: 'school-A', country: 'America' }, { type: 'senior', schoolName: 'school-B', country: 'England' }, { type: 'junior', schoolName: 'school-C', country: 'German' }, { type: 'junior', schoolName: 'school-D', country: 'Italy' }, ];

const res = arr.reduce((acc, {type, schoolName, country}) => {
  if(!acc[type]) acc[type] = {};
  acc[type][country] = schoolName;
  return acc;
}, {});
console.log(res);

【讨论】:

    【解决方案2】:

    我认为这是解决您的问题的简单易读的解决方案(如果同一 country 的多个实例出现在同一 type 中,则最后一次出现将覆盖所有以前的出现)

    let data = [
      { type: 'senior', schoolName: 'school-A', country: 'America' },
      { type: 'senior', schoolName: 'school-B', country: 'England' },
      { type: 'junior', schoolName: 'school-C', country: 'German' },
      { type: 'junior', schoolName: 'school-D', country: 'Italy' }, 
    ];
    
    let res = {};
    
    data.forEach(e => {
      if(!res[e.type])
        res[e.type] = {};
        
      res[e.type][e.country] = e.schoolName;
    });
    
    console.log(res);

    【讨论】:

    • 以这种方式拥有一个 for each 确实会产生副作用,它会在其范围之外操作一个对象,即res。由于 OP 要求在语法上最干净的方式,我认为 forEach 不是最好的(然后,我再次投票结束这个问题,因为它是基于这句话的意见)
    猜你喜欢
    • 2020-06-17
    • 2020-10-04
    • 2022-01-23
    • 2022-01-15
    • 2018-02-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多