有人知道一种方法(lodash如果可能的话)通过对象键分组对象数组,然后根据分组创建一个新的对象数组吗?例如,我有一个汽车对象数组:

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'
    },
];

我想创建一个新的汽车对象数组,由make分组:

const cars = {
    'audi': [
        {
            'model': 'r8',
            'year': '2012'
        }, {
            'model': 'rs5',
            'year': '2013'
        },
    ],

    'ford': [
        {
            'model': 'mustang',
            'year': '2012'
        }, {
            'model': 'fusion',
            'year': '2015'
        }
    ],

    'kia': [
        {
            'model': 'optima',
            'year': '2012'
        }
    ]
}

当前回答

我喜欢@metakunfu的答案,但它并没有提供预期的输出。 下面是在最终的JSON有效负载中去除“make”的更新。

var 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'
    },
];

result = cars.reduce((h, car) => Object.assign(h, { [car.make]:( h[car.make] || [] ).concat({model: car.model, year: car.year}) }), {})

console.log(JSON.stringify(result));

输出:

{  
   "audi":[  
      {  
         "model":"r8",
         "year":"2012"
      },
      {  
         "model":"rs5",
         "year":"2013"
      }
   ],
   "ford":[  
      {  
         "model":"mustang",
         "year":"2012"
      },
      {  
         "model":"fusion",
         "year":"2015"
      }
   ],
   "kia":[  
      {  
         "model":"optima",
         "year":"2012"
      }
   ]
}

其他回答

const reGroup = (list, key) => {
    const newGroup = {};
    list.forEach(item => {
        const newItem = Object.assign({}, item);
        delete newItem[key];
        newGroup[item[key]] = newGroup[item[key]] || [];
        newGroup[item[key]].push(newItem);
    });
    return newGroup;
};
const animals = [
  {
    type: 'dog',
    breed: 'puddle'
  },
  {
    type: 'dog',
    breed: 'labradoodle'
  },
  {
    type: 'cat',
    breed: 'siamese'
  },
  {
    type: 'dog',
    breed: 'french bulldog'
  },
  {
    type: 'cat',
    breed: 'mud'
  }
];
console.log(reGroup(animals, 'type'));
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(reGroup(cars, 'make'));

添加Array.prototype.group和Array.prototype.groupToMap的提案现在处于阶段3!

当它达到阶段4并在大多数主流浏览器上实现时,你将能够这样做:

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 grouped = cars.group(item => item.make);
console.log(grouped);

这将输出:

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

在那之前,你可以使用这个core-js polyfill:

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 grouped = cars.group(item => item.make); //console.log(grouped); // Optional: remove the "make" property from resulting object const entriesUpdated = Object .entries(grouped) .map(([key, value]) => [ key, value.map(({make, ...rest}) => rest) ]); const noMake = Object.fromEntries(entriesUpdated); console.log(noMake); <script src="https://unpkg.com/core-js-bundle@3.26.1/minified.js"></script>

试试这个吧,我觉得挺好用的。

让分组= _。groupBy(汽车,“使”);

注意:使用lodash lib,所以包括它。

提莫的答案是我会怎么做。简单的_。groupBy,并允许在分组结构中的对象中有一些重复。

然而,OP还要求删除重复的make键。如果你想从头到尾:

var grouped = _.mapValues(_.groupBy(cars, 'make'),
                          clist => clist.map(car => _.omit(car, 'make')));

console.log(grouped);

收益率:

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

如果你想使用Underscore.js来实现这个功能,请注意它的_. js版本。mapValues被称为_.mapObject。

下面是您自己的groupBy函数,它是来自https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore的代码的泛化

函数groupBy(xs, f) { 返回x。减少((r, v, i, a、k = f (v)) = > ((r [k] | | (r [k] = [])) .push (v), r), {}); } Const cars = [{make: 'audi',型号:'r8',年份:'2012'},{make: 'audi',型号:'rs5',年份:'2013'},{make: 'ford',型号:'mustang',年份:'2012'},{make: 'ford',型号:'fusion',年份:'2015'},{make: 'kia',型号:'optima',年份:'2012'}]; const result = groupBy(cars, (c) => c.make); console.log(结果);