【问题标题】:Array of objects to array of objects grouped by propery对象数组到按属性分组的对象数组
【发布时间】:2020-06-04 16:00:48
【问题描述】:

我正在努力想出一种有效的方法来按属性将对象数组分组到另一个数组中。

我从相关问题和答案中检查了一些解决方案,但努力实现所需的数据结构。

样本数据传入数据(取自this q

const cars = [{
  'make': 'audi',
  'model': 'r8',
  'year': '2012'
}, {
  'make': 'audi',
  'model': 'rs5',
  'year': '2013'
}, {
  'make': 'ford',
  'model': 'mustang',
  'year': '2012'
}, {
  'make': 'ford',
  'model': 'fusion',
  'year': '2015'
}, {
  'make': 'kia',
  'model': 'optima',
  'year': '2012'
}, ];

这是我想要实现的目标:

const carsTransformed = [{
  'audi': [{
    'model': 'r8',
    'year': '2012'
  }, {
    'model': 'rs5',
    'year': '2013'
  },],
},
{
  'ford': [{
    'model': 'mustang',
    'year': '2012'
  }, {
    'model': 'fusion',
    'year': '2015'
  }],
},
{
  'kia': [{
    'model': 'optima',
    'year': '2012'
  }]
}
];

目前尝试使用

const arrayGroupBy = (array, property) => {
  return array.reduce((map, object) => {
    (map[object[property]] = map[object[property]] || []).push(object);
    return map;
  }, {});
};

尝试通过Object.entries(obj).map() 操作生成的对象得到一些奇怪的结果:(

我将不胜感激有关如何实现这一目标的任何想法。

编辑:尽量不使用任何第三方库。

【问题讨论】:

    标签: javascript arrays object grouping


    【解决方案1】:

    这不是很紧凑,但使用 delete 可以从对象中删除属性。

    const groupBy = (obj, property = 'id') =>
      Object.entries(obj.reduce((map, item) => {
        var key = item[property]
        map[key] = map[key] || []
        const cleaned = Object.assign({}, item)
        delete cleaned[property]
        map[key].push(cleaned)
        return map
      }, {}))
      .map(([k, a]) => ({
        [k]: a
      }))
    
    const cars = [{
      'make': 'audi',
      'model': 'r8',
      'year': '2012'
    }, {
      'make': 'audi',
      'model': 'rs5',
      'year': '2013'
    }, {
      'make': 'ford',
      'model': 'mustang',
      'year': '2012'
    }, {
      'make': 'ford',
      'model': 'fusion',
      'year': '2015'
    }, {
      'make': 'kia',
      'model': 'optima',
      'year': '2012'
    }, ];
    
    console.log(groupBy(cars, 'make'))

    【讨论】:

    • 感谢您的回答,它仍然会返回一个对象
    • 奇怪的是你希望它隐藏在一个数组中,但这是一个简单的改变。添加.map(([k,a]) => ({ [k]: a })) 将使其进入数组
    • 编辑它以返回一个数组而不仅仅是对象
    【解决方案2】:

     let cars = [{
      'make': 'audi',
      'model': 'r8',
      'year': '2012'
    }, {
      'make': 'audi',
      'model': 'rs5',
      'year': '2013'
    }, {
      'make': 'ford',
      'model': 'mustang',
      'year': '2012'
    }, {
      'make': 'ford',
      'model': 'fusion',
      'year': '2015'
    }, {
      'make': 'kia',
      'model': 'optima',
      'year': '2012'
    }, ];
    
    let rqObj = cars.reduce((acc,ele)=>{
      let nObj = JSON.parse(JSON.stringify(ele));
      delete nObj['make'];
      let obj = {[ele.make]:[nObj]};
      let pos = acc.findIndex(el=>Object.keys(el)[0]==ele.make);
      (pos == -1) ? acc.push(obj) : acc[pos][ele.make] = [...acc[pos][ele.make],...obj[ele.make]];
      return acc;
    },[])
    console.log(rqObj)

    【讨论】:

      【解决方案3】:
      const carsTransformed = [...new Set(cars.map(c => c.make))].map(make => {
          return {
              [make]: cars.filter(cs => cs.make === make)
          }
      })
      

      【讨论】:

        【解决方案4】:

        如果你想要 Object 这里是解决方案:

        const carsTransformedObject = cars.reduce((acc, next) => {
          if (acc[next.make]) {
            acc[next.make].push({model: next.model, year: next.year})
          } else {
            acc[next.make] = [{model: next.model, year: next.year}]
          }
          return acc
        }, {})
        

        如果您希望此对象像您展示的那样位于数组中,请执行以下操作: const carTransformed = [carsTransformedObject]

        就是这样?

        You can try it here

        【讨论】:

          【解决方案5】:
          let group = {};
          cars.forEach((c) => {
              if (!group[c.make]) group[c.make] = [];
              group[c.make] = [...group[c.make], cars.filter(m => m.make === c.make)];
          });
          console.log(group);
          

          或者您可以通过lodash library 实现此目的

          _.mapValues(_.groupBy(cars, 'make'));

          【讨论】:

          • 感谢您的回答。当我需要一个对象数组时,这仍然会返回一个对象。
          【解决方案6】:

          可能是这样的:

          const cars = [{
            'make': 'audi',
            'model': 'r8',
            'year': '2012'
          }, {
            'make': 'audi',
            'model': 'rs5',
            'year': '2013'
          }, {
            'make': 'ford',
            'model': 'mustang',
            'year': '2012'
          }, {
            'make': 'ford',
            'model': 'fusion',
            'year': '2015'
          }, {
            'make': 'kia',
            'model': 'optima',
            'year': '2012'
          }, ];
          
          function carsTransformed(_cars){
          	var out = {};
          	for(var key in _cars){
          		var car_brand = _cars[key].make;
          		if(!out[car_brand]){
          			out[car_brand] = [];
          		}
          		delete(_cars[key].make);
          		out[car_brand].push(_cars[key]);
          	}
          	return out;
          }
          console.log(carsTransformed(cars));

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-09-22
            • 1970-01-01
            • 2019-04-15
            • 2015-12-31
            • 2021-11-25
            • 2020-05-14
            • 2021-01-30
            • 1970-01-01
            相关资源
            最近更新 更多