如何按键对一组对象进行分组?

Posted

技术标签:

【中文标题】如何按键对一组对象进行分组?【英文标题】:How can I group an array of objects by key? 【发布时间】:2022-01-08 05:13:21 【问题描述】:

有没有人知道一种方法(如果可能的话,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'
        
    ]

【问题讨论】:

您的结果无效。 是否有类似的方法来获取地图而不是对象? 如果您使用的是 Typescript(这不是 OP 的情况),您已经拥有 groupBy 方法。您可以使用your_array.groupBy(...) your_array.groupBy(...) 不存在!! 【参考方案1】:

在纯 javascript 中,您可以将 Array#reduce 与对象一起使用

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(function (r, a) 
        r[a.make] = r[a.make] || [];
        r[a.make].push(a);
        return r;
    , Object.create(null));

console.log(result);
.as-console-wrapper  max-height: 100% !important; top: 0; 

【讨论】:

如何迭代result 结果? 您可以使用Object.entries 获取条目并遍历键/值对。 有没有办法在分组后从数据集中删除make?它占用了额外的空间。 一如既往的最佳答案。你为什么要传递 Object.create(null)? @Alex,请看这里:***.com/questions/38068424/…【参考方案2】:

Timo's answer 我会这样做。简单_.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 执行此操作,请注意其版本的 _.mapValues 称为 _.mapObject

【讨论】:

【参考方案3】:

您正在寻找_.groupBy()

如果需要,从对象中删除您分组依据的属性应该很简单:

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 = _.groupBy(cars, car => car.make);

console.log(grouped);
<script src='https://cdn.jsdelivr.net/lodash/4.17.2/lodash.min.js'></script>

【讨论】:

如果你想让它更短,var grouped = _.groupBy(cars, 'make'); 根本不需要函数,如果访问器是一个简单的属性名称。 “_”代表什么? @AdrianGrzywaczewski 这是名称间距“lodash”或“下划线”的默认约定。现在图书馆是模块化的,它不再需要,即。 npmjs.com/package/lodash.groupby 我怎样才能对结果进行交互? 我相信这将与 Object.keys(grouped)【参考方案4】:

完全没有理由下载 3rd 方库来解决这个简单的问题,就像上面的解决方案所建议的那样。

在 es6 中通过某个 key 对对象的 list 进行分组的单行版本:

const groupByKey = (list, key) => list.reduce((hash, obj) => (...hash, [obj[key]]:( hash[obj[key]] || [] ).concat(obj)), )

过滤掉没有key的对象的较长版本:

function groupByKey(array, key) 
   return array
     .reduce((hash, obj) => 
       if(obj[key] === undefined) return hash; 
       return Object.assign(hash,  [obj[key]]:( hash[obj[key]] || [] ).concat(obj))
     , )



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

console.log(groupByKey(cars, 'make'))

注意:最初的问题似乎是询问如何按品牌对汽车进行分组,但在每个组中都省略了品牌。因此,没有 3rd 方库的简短答案如下所示:

const groupByKey = (list, key, omitKey=false) => list.reduce((hash, [key]:value, ...rest) => (...hash, [value]:( hash[value] || [] ).concat(omitKey ? ...rest : [key]:value, ...rest) ), )

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

console.log(groupByKey(cars, 'make', omitKey:true))

【讨论】:

这绝对不是es5 它的工作原理!谁能详细说明这个reduce函数? 我喜欢您的两个答案,但我看到它们都提供“make”字段作为每个“make”数组的成员。我已经根据您的答案提供了一个答案,其中交付的输出与预期的输出相匹配。谢谢!【参考方案5】:

这是您自己的 groupBy 函数,它是对以下代码的概括:https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore

function groupBy(xs, f) 
  return xs.reduce((r, v, i, a, k = f(v)) => ((r[k] || (r[k] = [])).push(v), r), );


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 result = groupBy(cars, (c) => c.make);
console.log(result);

【讨论】:

我喜欢这个答案,因为您也可以使用嵌套属性 - 非常好。我刚刚为 Typescript 更改了它,这正是我想要的 :)【参考方案6】:

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'
].reduce((r, car) => 

  const 
    model,
    year,
    make
   = car;

  r[make] = [...r[make] || [], 
    model,
    year
  ];

  return r;
, );

console.log(cars);

【讨论】:

需要紧急帮助如何在上面存储,例如 [ "audi": [ "model": "r8", "year": "2012" ] , "ford": [ "model": "r9", "year": "2021" ] ...] 每个对象【参考方案7】:

也可以使用简单的for 循环:

 const result = ;

 for(const make, model, year of cars) 
   if(!result[make]) result[make] = [];
   result[make].push( model, year );
 

【讨论】:

而且可能更快,更简单。我已将您的 sn-p 扩展为更具动态性,因为我不想输入 db 表中的一长串字段。另请注意,您需要将 const 替换为 let。 for ( let TABLE_NAME, ...fields of source) result[TABLE_NAME] = result[TABLE_NAME] || []; result[TABLE_NAME].push( ...fields ); 直到,谢谢! medium.com/@mautayro/…【参考方案8】:

对于 JS Arrays 示例,我将 REAL GROUP BY 与此任务 here 完全相同。

const inputArray = [ 
     Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" ,
     Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" ,
     Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" ,
     Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" ,
     Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" ,
     Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" ,
     Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" ,
     Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" 
];

var outObject = inputArray.reduce(function(a, e) 
  // GROUP BY estimated key (estKey), well, may be a just plain key
  // a -- Accumulator result object
  // e -- sequentally checked Element, the Element that is tested just at this itaration

  // new grouping name may be calculated, but must be based on real value of real field
  let estKey = (e['Phase']); 

  (a[estKey] ? a[estKey] : (a[estKey] = null || [])).push(e);
  return a;
, );

console.log(outObject);

【讨论】:

【参考方案9】:

您可以尝试修改 _.groupBy 函数每次迭代调用的函数内的对象。 注意源数组改变了他的元素!

var res = _.groupBy(cars,(car)=>
    const makeValue=car.make;
    delete car.make;
    return makeValue;
)
console.log(res);
console.log(cars);

【讨论】:

虽然这段代码可以解决问题,including an explanation 解决问题的方式和原因确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人!请编辑您的答案以添加解释,并说明适用的限制和假设。 这对我来说似乎是最好的答案,因为您只需遍历数组一次即可获得所需的结果。无需使用其他函数来删除make 属性,而且它也更具可读性。【参考方案10】:

创建一个可以重复使用的方法

Array.prototype.groupBy = function(prop) 
      return this.reduce(function(groups, item) 
        const val = item[prop]
        groups[val] = groups[val] || []
        groups[val].push(item)
        return groups
      , )
    ;

然后你可以在下面按任何标准分组

const groupByMake = cars.groupBy('make');
        console.log(groupByMake);

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'
    ,
];
  //re-usable method
Array.prototype.groupBy = function(prop) 
	  return this.reduce(function(groups, item) 
		const val = item[prop]
		groups[val] = groups[val] || []
		groups[val].push(item)
		return groups
	  , )
	;
  
 // initiate your groupBy. Notice the recordset Cars and the field Make....
  const groupByMake = cars.groupBy('make');
		console.log(groupByMake);
    
    //At this point we have objects. You can use Object.keys to return an array

【讨论】:

【参考方案11】:

对于 key 可以为 null 的情况,我们希望将它们分组为 others

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',
            'make':'kia','model':'optima','year':'2033',
            'make':null,'model':'zen','year':'2012',
            'make':null,'model':'blue','year':'2017',

           ];


 result = cars.reduce(function (r, a) 
        key = a.make || 'others';
        r[key] = r[key] || [];
        r[key].push(a);
        return r;
    , Object.create(null));

【讨论】:

【参考方案12】:

只需简单的 forEach 循环即可在此处运行,无需任何库

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'
,
];
let ObjMap =;

  cars.forEach(element => 
    var makeKey = element.make;
     if(!ObjMap[makeKey]) 
       ObjMap[makeKey] = [];
     

    ObjMap[makeKey].push(
      model: element.model,
      year: element.year
    );
   );
   console.log(ObjMap);

【讨论】:

最优雅易读的解决方案【参考方案13】:

同意,除非您经常使用这些,否则不需要外部库。尽管有类似的解决方案可用,但如果您想了解正在发生的事情,我发现其中一些解决方案很难遵循here is a gist,该解决方案与 cmets 有一个解决方案。

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

/**
 * Groups an array of objects by a key an returns an object or array grouped by provided key.
 * @param array - array to group objects by key.
 * @param key - key to group array objects by.
 * @param removeKey  - remove the key and it's value from the resulting object.
 * @param outputType - type of structure the output should be contained in.
 */
const groupBy = (
  inputArray,
  key,
  removeKey = false,
  outputType = ,
) => 
  return inputArray.reduce(
    (previous, current) => 
      // Get the current value that matches the input key and remove the key value for it.
      const 
        [key]: keyValue
       = current;
      // remove the key if option is set
      removeKey && keyValue && delete current[key];
      // If there is already an array for the user provided key use it else default to an empty array.
      const 
        [keyValue]: reducedValue = []
       = previous;

      // Create a new object and return that merges the previous with the current object
      return Object.assign(previous, 
        [keyValue]: reducedValue.concat(current)
      );
    ,
    // Replace the object here to an array to change output object to an array
    outputType,
  );
;

console.log(groupBy(cars, 'make', true))

【讨论】:

【参考方案14】:

试试这个对我来说效果很好。

let grouped = _.groupBy(cars, 'make');

注意:使用 lodash 库,所以包含它。

【讨论】:

Uncaught ReferenceError: _ is not defined - 你应该清楚你的解决方案需要安装一个第三方库来解决这个问题。 对不起,我想每个人都知道。 _ 代表并主要用于 lodash lib。所以你需要使用 lodash。请阅读问题,这样您就会知道他/她在要求 lodash。好吧,谢谢。我会记住这一点。永远不要忘记写 lib。 你应该编辑你的答案以包括你正在使用一个库。【参考方案15】:

原型版本也使用 ES6。 基本上,这使用reduce函数传入一个累加器和当前项,然后使用它根据传入的键构建“分组”数组。 reduce 的内部部分可能看起来很复杂,但本质上它是在测试传入对象的键是否存在,如果不存在则创建一个空数组并将当前项附加到新创建的数组,否则使用展开运算符传入当前键数组的所有对象并附加当前项。希望这对某人有帮助!。

Array.prototype.groupBy = function(k) 
  return this.reduce((acc, item) => ((acc[item[k]] = [...(acc[item[k]] || []), item]), acc),);
;

const projs = [
  
    project: "A",
    timeTake: 2,
    desc: "this is a description"
  ,
  
    project: "B",
    timeTake: 4,
    desc: "this is a description"
  ,
  
    project: "A",
    timeTake: 12,
    desc: "this is a description"
  ,
  
    project: "B",
    timeTake: 45,
    desc: "this is a description"
  
];

console.log(projs.groupBy("project"));

【讨论】:

【参考方案16】:

另一种解决方案:

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


const reducedCars = cars.reduce((acc,  make, model, year ) => (
     
      ...acc, 
      [make]: acc[make] ? [ ...acc[make],  model, year ] : [  model, year  ],
    
 ), );

console.log(reducedCars);

【讨论】:

【参考方案17】:

你也可以像这样使用array#forEach()方法:

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

let newcars = 

cars.forEach(car => 
  newcars[car.make] ? // check if that array exists or not in newcars object
    newcars[car.make].push(model: car.model, year: car.year)  // just push
   : (newcars[car.make] = [], newcars[car.make].push(model: car.model, year: car.year)) // create a new array and push
)

console.log(newcars);

【讨论】:

【参考方案18】:
function groupBy(data, property) 
  return data.reduce((acc, obj) => 
    const key = obj[property];
    if (!acc[key]) 
      acc[key] = [];
    
    acc[key].push(obj);
    return acc;
  , );

groupBy(people, 'age');

【讨论】:

【参考方案19】:

我喜欢写它,没有依赖/复杂性,只是纯粹的简单 js。

const mp = 
const cars = [
  
    model: 'Imaginary space craft SpaceX model',
    year: '2025'
  ,
  
    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'
  
]

cars.forEach(c => 
  if (!c.make) return // exit (maybe add them to a "no_make" category)

  if (!mp[c.make]) mp[c.make] = [ model: c.model, year: c.year ]
  else mp[c.make].push( model: c.model, year: c.year )
)

console.log(mp)

【讨论】:

【参考方案20】:

我喜欢@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"
      
   ]

【讨论】:

【参考方案21】:

使用 lodash/fp,您可以使用 _.flow() 创建一个函数,该函数首先按一个键分组,然后映射每个组,并从每个项目中省略一个键:

const  flow, groupBy, mapValues, map, omit  = _;

const groupAndOmitBy = key => flow(
  groupBy(key),
  mapValues(map(omit(key)))
);

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 groupAndOmitMake = groupAndOmitBy('make');

const result = groupAndOmitMake(cars);

console.log(result);
.as-console-wrapper  max-height: 100% !important; top: 0; 
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>

【讨论】:

【参考方案22】:

打字稿中的对象分组数组:

groupBy (list: any[], key: string): Map<string, Array<any>> 
    let map = new Map();
    list.map(val=> 
        if(!map.has(val[key]))
            map.set(val[key],list.filter(data => data[key] == val[key]));
        
    );
    return map;
);

【讨论】:

当您搜索每个键时,这看起来效率很低。搜索的复杂度很可能是 O(n)。 使用 Typescript 你已经有了 groupBy 方法。您可以使用your_array.groupBy(...)【参考方案23】:

我做了一个基准测试来测试每个不使用外部库的解决方案的性能。

JSBen.ch

@Nina Scholz 发布的reduce() 选项似乎是最佳选项。

【讨论】:

【参考方案24】:

添加了Array.prototype.groupByArray.prototype.groupByToMap 的A proposal 现在处于第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.groupBy(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' 
  ]

在那之前,你可以使用this 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.groupBy(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);
&lt;script src="https://unpkg.com/core-js-bundle@3.20.1/minified.js"&gt;&lt;/script&gt;

【讨论】:

【参考方案25】:

如果您不想输入所有字段,请在 @Jonas_Wilms 的 answer 上构建:

    var result = ;

    for ( let  first_field, ...fields  of your_data ) 
     
       result[first_field] = result[first_field] || [];
       result[first_field].push( ...fields ); 
    

我没有做任何基准测试,但我相信使用 for 循环也会比 this answer 中建议的任何方法更有效。

【讨论】:

for...of 循环效率最低。为 forEach 循环使用 for(i...)【参考方案26】:
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'));

【讨论】:

【参考方案27】:

这是一个受 Java 中的 Collectors.groupingBy() 启发的解决方案:

function groupingBy(list, keyMapper) 
  return list.reduce((accummalatorMap, currentValue) => 
    const key = keyMapper(currentValue);
    if(!accummalatorMap.has(key)) 
      accummalatorMap.set(key, [currentValue]);
     else 
      accummalatorMap.set(key, accummalatorMap.get(key).push(currentValue));
    
    return accummalatorMap;
  , new Map());

这将给出一个 Map 对象。

// Usage

const carMakers = groupingBy(cars, car => car.make);

【讨论】:

【参考方案28】:

这是另一个解决方案。根据要求。

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

function groupBy() 
  const key = 'make';
  return cars.reduce((acc, x) => (
    ...acc,
    [x[key]]: (!acc[x[key]]) ? [
      model: x.model,
      year: x.year
    ] : [...acc[x[key]], 
      model: x.model,
      year: x.year
    ]
  ), )

输出:

console.log('Grouped by make key:',groupBy())

【讨论】:

以上是关于如何按键对一组对象进行分组?的主要内容,如果未能解决你的问题,请参考以下文章

如何对一组对象进行分组并将其映射到不同的结构?

Mysql,如何使用另一列的最大值对一组行进行分组?

在 Colorbox 中对一组元素进行分组

当行中的时间戳小于或等于某个值时,使用分析函数对一组记录进行分组

Java 对数据分组

按键分组对象数组 - javascript