1

Trying to figure out what the best practice for taking one array of objects in JS and combining the properties of it's indexes based upon a shared property value.

Basically, I have an array of users who have applied to a certain class where the class the user applied to is an array. However, every single class that the same user has applied to is its own separate index. The goal would be to combine all of a user's classes within one index (the array) instead of having duplicates.

Ex.

let someArray = [
    {
        name: 'Jim',
        class: [
            {
                name: 'Sports Journalism',
                field: 'Journalism'
            }
        ]
    },
    {
        name: 'Pam',
        class: [
            {
                name: 'Fine Arts',
                field: 'Art'
            }
        ]
    },
    {
        name: 'Jim',
        class: [
            {
                name: 'Sales 101',
                field: 'Business'
            }
        ]
    }
]
// something like this where we would want all of Jim's
// classes to be in one class array on just one index
Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
  • Possible duplicate of [How to group an array of objects by key](https://stackoverflow.com/questions/40774697/how-to-group-an-array-of-objects-by-key) – Anurag Srivastava May 16 '19 at 12:24

2 Answers2

1

Use reduce:

let someArray = [{name:'Jim',class:[{name:'Sports Journalism',field:'Journalism'}]},{name:'Pam',class:[{name:'Fine Arts',field:'Art'}]},{name:'Jim',class:[{name:'Sales 101',field:'Business'}]}];
const res = Object.values(someArray.reduce((acc, { name, class: [...classObj] }) => {
  (acc[name] = acc[name] || { name, class: [] }).class.push(classObj);
  return acc;
}, {}));
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: auto; }
Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
0

Here's a group by function that will do the job for all the similar user names:

function groupBy(data, fields, sumBy='class') {
  let r=[], cmp= (x,y) => fields.reduce((a,b)=> a && x[b]==y[b], true);
  data.forEach(x=> {
    let y=r.find(z=>cmp(x,z));
    let w= [...fields,sumBy].reduce((a,b) => (a[b]=x[b],a), {})
    y ? y[sumBy]=[...y[sumBy], ...x[sumBy]] : r.push(w);
  });
  return r;
}

And you can use it like this:

let oh = groupBy(someArray, ['name']);

Inspired from this question: Most efficient method to groupby on a array of objects

Mehdi Benmoha
  • 3,694
  • 3
  • 23
  • 43