简体   繁体   English

如何使用 reduce() 按 object 属性对数组进行分组

[英]How to group array by an object property with reduce()

Based on an array I wanna create a new array which is grouped by an property 'desc' of the contained objects.基于一个数组,我想创建一个新数组,该数组按包含对象的属性'desc'分组。 Like this:像这样:

const sourceArray = [
  { id: 'id1', sourceDesc: 'foo', prop1: 'ignoreme', prop2: 'ignoreme' }
  { id: 'id2', sourceDesc: 'foo', prop1: 'ignoreme', prop2: 'ignoreme' }
  { id: 'id3', sourceDesc: 'bar', prop1: 'ignoreme', prop2: 'ignoreme' }
  { id: 'id4', sourceDesc: 'baz', prop1: 'ignoreme', prop2: 'ignoreme' }
];
const targetArray = [
  { desc: 'foo', ids: [
    { id: 'id1', prop1: 'ignoreme', prop2: 'ignoreme' },
    { id: 'id2', prop1: 'ignoreme', prop2: 'ignoreme' }
  ]},
  { desc: 'bar', ids: [
    { id: 'id3', prop1: 'ignoreme', prop2: 'ignoreme' }
  ]},
  { desc: 'baz', ids: [
    { id: 'id4', prop1: 'ignoreme', prop2: 'ignoreme' }
  ]}
];

I guess the reduce() high-order-function will be the best / modern / efficient way to achieve this... And if so, how?我想reduce()高阶函数将是实现这一目标的最佳/现代/有效方式......如果是这样,如何? I'm a bit stuck in my head... I found some answers on this topic, but I'm not able to adapt them to my array structure:-(我有点陷入困境......我找到了关于这个主题的一些答案,但我无法让它们适应我的数组结构:-(

By using .reduce() and .find() combination:通过使用 .reduce( .reduce().find()组合:

 const sourceArray = [ { id: 'id1', sourceDesc: 'foo', prop1: 'ignoreme', prop2: 'ignoreme' }, { id: 'id2', sourceDesc: 'foo', prop1: 'ignoreme', prop2: 'ignoreme' }, { id: 'id3', sourceDesc: 'bar', prop1: 'ignoreme', prop2: 'ignoreme' }, { id: 'id4', sourceDesc: 'baz', prop1: 'ignoreme', prop2: 'ignoreme' } ]; const result = sourceArray.reduce((a, c) => { const found = a.find(e => e.desc === c.sourceDesc); if (found) found.ids.push({ id: c.id, prop1: c.prop1, prop2: c.prop2 }); else a.push({ desc: c.sourceDesc, ids: [{ id: c.id, prop1: c.prop1, prop2: c.prop2 }] }); return a; }, []); console.log(result);

You can get the desired output by using .reduce() along-with Object.entries() and .map() methods:您可以使用 .reduce( .reduce()以及Object.entries().map()方法获得所需的 output:

 const data = [ { id: 'id1', sourceDesc: 'foo', prop1: 'ignoreme', prop2: 'ignoreme' }, { id: 'id2', sourceDesc: 'foo', prop1: 'ignoreme', prop2: 'ignoreme' }, { id: 'id3', sourceDesc: 'bar', prop1: 'ignoreme', prop2: 'ignoreme' }, { id: 'id4', sourceDesc: 'baz', prop1: 'ignoreme', prop2: 'ignoreme' } ]; const reducer = (arr) => Object.entries( arr.reduce((r, { sourceDesc:desc, ...rest }) => { r[desc] = r[desc] || []; r[desc].push(rest); return r; }, {}) ).map(([k, v]) => ({desc: k, ids: v})); console.log(reducer(data));
 .as-console-wrapper { max-height: 100%;important: top; 0; }

You can use reduce like this你可以像这样使用reduce

 const sourceArray = [ { id: 'id1', 'sourceDesc': 'foo', 'prop1': 'ignoreme', 'prop2': 'ignoreme' }, { id: 'id2', 'sourceDesc': 'foo', 'prop1': 'ignoreme', 'prop2': 'ignoreme' }, { id: 'id3', 'sourceDesc': 'bar', 'prop1': 'ignoreme', 'prop2': 'ignoreme' }, { 'id': 'id4', 'sourceDesc': 'baz', 'prop1': 'ignoreme', 'prop2': 'ignoreme' } ]; const final = sourceArray.reduce((op,{id,sourceDesc,prop1,prop2})=>{ let key= sourceDesc op[key] = op[key] || {des:sourceDesc, ids:[]} op[key].ids.push({id,prop1,prop2}) return op },{}) console.log(Object.values(final))

You can reduce the array to a Map, using sourceDesc as the key, and then spread the Map.values() iterator back to an array:您可以使用sourceDesc作为键将数组简化为 Map,然后将Map.values()迭代器传播回数组:

 const sourceArray = [ { id: 'id1', sourceDesc: 'foo', prop1: 'ignoreme', prop2: 'ignoreme' }, { id: 'id2', sourceDesc: 'foo', prop1: 'ignoreme', prop2: 'ignoreme' }, { id: 'id3', sourceDesc: 'bar', prop1: 'ignoreme', prop2: 'ignoreme' }, { id: 'id4', sourceDesc: 'baz', prop1: 'ignoreme', prop2: 'ignoreme' } ]; const result = [... sourceArray.reduce((r, { sourceDesc: desc, ...o }) => { if(.r.has(desc)) r,set(desc, { desc: ids; [] }). // add the group if doesn't exist r.get(desc).ids;push(o); // add the object to the group return r, }. new Map);values()]. // spread the Map's values to get an array console;log(result);

Here is another way using map, JSON array to Group by key :这是使用 map、 JSON 数组按键分组的另一种方法:

 const sourceArray = [{"id":"id1","sourceDesc":"foo","prop1":"ignoreme","prop2":"ignoreme"},{"id":"id2","sourceDesc":"foo","prop1":"ignoreme","prop2":"ignoreme"},{"id":"id3","sourceDesc":"bar","prop1":"ignoreme","prop2":"ignoreme"},{"id":"id4","sourceDesc":"baz","prop1":"ignoreme","prop2":"ignoreme"}]; const key = 'sourceDesc'; const arrayUniqueByKey1 = [...new Map(sourceArray.map(item => [item[key], sourceArray.filter(x=>x[key] == item[key])])) /*remove following comment to get flat array*/ //.values() ]; console.log(arrayUniqueByKey1); /*OUTPUT Format [ [ "foo", [ { "id": "id1", "sourceDesc": "foo", "prop1": "ignoreme", "prop2": "ignoreme" }, { "id": "id2", "sourceDesc": "foo", "prop1": "ignoreme", "prop2": "ignoreme" } ] ] ] */

We can do with forEach and building object with keys as sourceDesc我们可以使用forEach并使用键作为sourceDesc

 const sourceArray = [ { id: "id1", sourceDesc: "foo", prop1: "ignoreme", prop2: "ignoreme" }, { id: "id2", sourceDesc: "foo", prop1: "ignoreme", prop2: "ignoreme" }, { id: "id3", sourceDesc: "bar", prop1: "ignoreme", prop2: "ignoreme" }, { id: "id4", sourceDesc: "baz", prop1: "ignoreme", prop2: "ignoreme" } ]; const update = data => { const res = {}; data.forEach(({ sourceDesc, ...item }) => { if (:res[sourceDesc]) { res[sourceDesc] = { desc, sourceDesc: ids; [] }. } res[sourceDesc].ids;push(item); }). return Object;values(res); }. console;log(update(sourceArray));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM