Travis Libby
Travis Libby

Reputation: 71

Loop through a collection and return a new collection where objects with the same id are combined

Let's say I have this javascript array.

var events = [
  {id: 1, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 2, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 2, name: 'Football Game', invitees: ['Gary', 'Jane','Bella']},
  {id: 3, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 4, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 5, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 5, name: 'Football Game', invitees: ['Ted', 'Laura']},
  {id: 5, name: 'Football Game', invitees: ['Jim', 'Samantha']},
];

What I need is to reduce this array to look like this:

var events = [
  {id: 1, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 2, name: 'Football Game', invitees: ['Gary', 'Jane','Bella']},
  {id: 3, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 4, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 5, name: 'Football Game', invitees: ['Gary', 'Jane', 'Ted', 'Laura', 'Jim', 'Samantha']}
];

Where the array has been reduced that there is only one object with each id and the invitees array within each object shows all invitees.

I'm having trouble just getting started with the basic logic here.

Upvotes: 1

Views: 39

Answers (2)

trincot
trincot

Reputation: 350766

You could use this ES6 functional programming style code:

var result = Array.from (
    events.reduce ( (acc, obj) => acc.set(obj.id,
        Object.assign({}, obj, {invitees: [...new Set(
            [...(acc.get(obj.id) || obj).invitees, ...obj.invitees] )]})
    ), new Map() ), ([id, obj]) => obj );

var events = [
  {id: 1, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 2, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 2, name: 'Football Game', invitees: ['Gary', 'Jane','Bella']},
  {id: 3, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 4, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 5, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 5, name: 'Football Game', invitees: ['Ted', 'Laura']},
  {id: 5, name: 'Football Game', invitees: ['Jim', 'Samantha']},
];

var result = Array.from (
    events.reduce ( (acc, obj) => acc.set(obj.id,
        Object.assign({}, obj, {invitees: [...new Set(
            [...(acc.get(obj.id) || obj).invitees, ...obj.invitees] )]})
    ), new Map() ), ([id, obj]) => obj );
  
console.log(result);

Upvotes: 0

Nenad Vracar
Nenad Vracar

Reputation: 122087

You can do this with reduce() and forEach() like this.

var events = [
  {id: 1, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 2, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 2, name: 'Football Game', invitees: ['Gary', 'Jane','Bella']},
  {id: 3, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 4, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 5, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 5, name: 'Football Game', invitees: ['Ted', 'Gary', 'Laura']},
  {id: 5, name: 'Football Game', invitees: ['Jim', 'Samantha']}
];

var o = {}
var result = events.reduce(function(r, e) {
  if (!o[e.id]) {
    o[e.id] = e;
    r.push(o[e.id]);
  } else {
    e.invitees.forEach(function(a) {
      if (o[e.id].invitees.indexOf(a) == -1) o[e.id].invitees.push(a);
    })
  }
  return r;
}, [])

console.log(result)

You could also use Set instead of forEach() loop to remove duplicates.

var events = [
  {id: 1, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 2, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 2, name: 'Football Game', invitees: ['Gary', 'Jane','Bella']},
  {id: 3, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 4, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 5, name: 'Football Game', invitees: ['Gary', 'Jane']},
  {id: 5, name: 'Football Game', invitees: ['Ted', 'Gary', 'Laura']},
  {id: 5, name: 'Football Game', invitees: ['Jim', 'Samantha']}
];

var o = {}
var result = events.reduce(function(r, e) {
  if (!o[e.id]) {
    o[e.id] = e;
    r.push(o[e.id]);
  } else {
    o[e.id].invitees = [...new Set(o[e.id].invitees.concat(e.invitees))];
  }
  return r;
}, [])

console.log(result)

Upvotes: 1

Related Questions