有人知道一种方法(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'
        }
    ]
}

当前回答

Prototype version using ES6 as well. Basically this uses the reduce function to pass in an accumulator and current item, which then uses this to build your "grouped" arrays based on the passed in key. the inner part of the reduce may look complicated but essentially it is testing to see if the key of the passed in object exists and if it doesn't then create an empty array and append the current item to that newly created array otherwise using the spread operator pass in all the objects of the current key array and append current item. Hope this helps someone!.

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"));

其他回答

提莫的答案是我会怎么做。简单的_。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。

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

在简单的Javascript中,你可以使用array# reduce对象

Var cars = [{make: 'audi',型号:'r8',年份:'2012'},{make: 'audi',型号:'rs5',年份:'2013'},{make: 'ford',型号:'mustang',年份:'2012'},{make: 'ford',型号:'fusion',年份:'2015'},{make: 'kia',型号:'optima',年份:'2012'}], 结果=汽车。Reduce(函数(r, a) { r (a。Make] = r[a]。Make] || []; r (a.make) .push(一个); 返回r; }, Object.create (null)); console.log(结果); .as-console-wrapper {max-height: 100% !重要;上图:0;}

这是一个通用函数,将返回Array groupBy自己的键。

const getSectionListGroupedByKey = < T > ( property: keyof T, List: Array < T > ): Array < { title: T[keyof T];data: Array < T > } > => { const sectionList: Array < { title: T[keyof T];data: Array < T > } > = []; if (!property || !List ? .[0] ? .[property]) { return []; } const groupedTxnListMap: Map < T[keyof T], Array < T >> = List.reduce((acc, cv) => { const keyValue: T[keyof T] = cv[property]; if (acc.has(keyValue)) { acc.get(keyValue) ? .push(cv); } else { acc.set(keyValue, [cv]); } return acc; }, new Map < T[keyof T], Array < T >> ()); groupedTxnListMap.forEach((value, key) => { sectionList.push({ title: key, data: value }); }); return sectionList; }; // Example 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 = getSectionListGroupedByKey('make', cars); console.log('result: ', result)

下面是您自己的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(结果);