如何按键对对象数组进行分组

Tru*_*ran 102 javascript arrays grouping object lodash

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

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'
    },
];
Run Code Online (Sandbox Code Playgroud)

我想制作一个新的汽车对象数组,按以下方式分组make:

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

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

    'kia': [
        {
            'model': 'optima',
            'year': '2012'
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

Nin*_*olz 206

在普通的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);
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Run Code Online (Sandbox Code Playgroud)

  • 一如既往的最佳答案。为什么要传递 Object.create(null) ? (4认同)
  • 我如何迭代“结果”结果? (3认同)
  • 您可以使用 [`Object.entries`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries) 获取条目并循环遍历键/值对。 (2认同)

Jon*_*ice 65

蒂莫的答案是我会怎么做.很简单_.groupBy,并允许在分组结构中的对象中进行一些复制.

但是OP也要求删除重复的make密钥.如果你想一路走下去:

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

console.log(grouped);
Run Code Online (Sandbox Code Playgroud)

产量:

{ audi:
   [ { model: 'r8', year: '2012' },
     { model: 'rs5', year: '2013' } ],
  ford:
   [ { model: 'mustang', year: '2012' },
     { model: 'fusion', year: '2015' } ],
  kia: [ { model: 'optima', year: '2012' } ] }
Run Code Online (Sandbox Code Playgroud)

如果您想使用Underscore.js执行此操作,请注意_.mapValues调用其版本_.mapObject.


Tim*_*imo 51

你在找_.groupBy().

如果需要,从对象中删除要分组的属性应该是微不足道的:

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

var grouped = _.groupBy(cars, function(car) {
  return car.make;
});

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


作为奖励,您可以使用ES6箭头功能获得更好的语法:

const grouped = _.groupBy(cars, car => car.make);
Run Code Online (Sandbox Code Playgroud)

  • 如果你想让它更短,`var grouped = _.groupBy(cars,'make');`如果访问者是一个简单的属性名,则根本不需要函数. (13认同)
  • 我该如何求结果呢? (2认同)
  • 我相信这将与 Object.keys(grouped) 一起使用 (2认同)

met*_*gfu 26

用于通过es6中的某个键对对象数组进行分组的简短版本:

result = array.reduce((h, obj) => Object.assign(h, { [obj.key]:( h[obj.key] || [] ).concat(obj) }), {})
Run Code Online (Sandbox Code Playgroud)

版本较长:

result = array.reduce(function(h, obj) {
  h[obj.key] = (h[obj.key] || []).concat(obj);
  return h; 
}, {})
Run Code Online (Sandbox Code Playgroud)

似乎原始问题询问如何通过make对汽车进行分组,但省略了每个组中的make.所以答案看起来像这样:

result = cars.reduce((h, {model,year,make}) => {
  return Object.assign(h, { [make]:( h[make] || [] ).concat({model,year})})
}, {})
Run Code Online (Sandbox Code Playgroud)


Jon*_*lms 14

它也可以通过一个简单的for循环:

 const result = {};

 for(const {make, model, year} of cars) {
   if(!result[make]) result[make] = [];
   result[make].push({ model, year });
 }
Run Code Online (Sandbox Code Playgroud)


cdi*_*ins 12

这是您自己的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);
Run Code Online (Sandbox Code Playgroud)


Syn*_*Cap 11

我要离开REAL GROUP BY了JS数组例如完全相同的这个任务在这里

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);
Run Code Online (Sandbox Code Playgroud)


Gau*_*tam 9

只需简单的 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);
Run Code Online (Sandbox Code Playgroud)


nic*_*xbs 7

您可以尝试通过_.groupBy func修改每次迭代调用的函数内的对象.请注意,源数组会更改其元素!

var res = _.groupBy(cars,(car)=>{
    const makeValue=car.make;
    delete car.make;
    return makeValue;
})
console.log(res);
console.log(cars);
Run Code Online (Sandbox Code Playgroud)


G.a*_*ziz 7

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, a) => {

  const {
    model,
    year,
    make
  } = a;

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

  return r;
}, {});

console.log(cars);
Run Code Online (Sandbox Code Playgroud)


Wah*_*ian 6

创建一个可以重用的方法

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
      }, {})
    };
Run Code Online (Sandbox Code Playgroud)

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

const groupByMake = cars.groupBy('make');
        console.log(groupByMake);
Run Code Online (Sandbox Code Playgroud)

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
      }, {})
    };
Run Code Online (Sandbox Code Playgroud)


dou*_*eep 6

添加提案Object.groupBy()Map.groupBy()已达到第 4 阶段!

它已经在大多数主要浏览器上实现(请参阅caniuse),因此您可以执行以下操作:

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 = Object.groupBy(cars, item => item.make);
console.log(grouped);
Run Code Online (Sandbox Code Playgroud)

这将输出:

{
  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' }
  ]
}
Run Code Online (Sandbox Code Playgroud)

您还可以使用这个 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 = Object.groupBy(cars, 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);
Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/core-js-bundle@3.31.1/minified.js"></script>
Run Code Online (Sandbox Code Playgroud)


exe*_*ian 5

对于 key 可以为 null 并且我们希望将它们分组为其他的情况

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));
Run Code Online (Sandbox Code Playgroud)


FFi*_*ire 5

另一种解决方案:

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);
Run Code Online (Sandbox Code Playgroud)