Paul Redmond
Paul Redmond

Reputation: 3296

Find count of object values that match between two arrays

I'm trying to get the count of matching data from two arrays (of objects). I want to find all instances of active being true for each group, and then create a new array that lists the count of matching items from the things array.

const groups = [
  {id: 234},
  {id: 423},
  {id: 474},
  {id: 864}
];

const things = [
  {id: 1, active: false, group: 234},
  {id: 2, active: true, group: 234},
  {id: 3, active: false, group: 234},
  {id: 4, active: true, group: 423},
  {id: 5, active: true, group: 423},
  {id: 6, active: false, group: 423}
];

The result I want to get is the group ID and the count of things that are active from the things array. I can use filter to return the active items, but how to get the count and get a new array like the output below?

I want the final results to look like :

[
  {group: 234, active: 1},
  {group: 423, active: 2}
];

Upvotes: 0

Views: 667

Answers (3)

Shidersz
Shidersz

Reputation: 17190

One possible solution is to use Array.reduce() to generate an object with the active count of the desired groups. Then, on a second step, you can use Array.map() to obtain the desired output.

const groups = [{id: 234}, {id: 423}, {id: 474}, {id: 864}];

const things = [
  {id: 1, active: false, group: 234},
  {id: 2, active: true, group: 234},
  {id: 3, active: false, group: 234},  
  {id: 4, active: true, group: 423},
  {id: 5, active: true, group: 423},  
  {id: 6, active: false, group: 423}
];

let groupsSet = new Set(groups.map(g => g.id));

let res = things.reduce((acc, {group, active}) =>
{
    if (active && groupsSet.has(group))
        acc[group] = (acc[group] || 0) + 1;

    return acc;
}, {});

res = Object.entries(res).map(([group, active]) => ({group, active}));
console.log(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386610

You could filter, filter and count the items.

const
    groups = [{ id: 234 }, { id: 423 }, { id: 474 }, { id: 864 }]
    things = [{ id: 1, active: false, group: 234 }, { id: 2, active: true, group: 234 }, { id: 3, active: false, group: 234 }, { id: 4, active: true, group: 423 }, { id: 5, active: true, group: 423 }, { id: 6, active: false, group: 423 }],
    groupsSet = new Set(groups.map(({ id }) => id)),
    result = Array.from(
        things
            .filter(({ active }) => active)
            .filter(({ group }) => groupsSet.has(group))
            .reduce((m, { group }) => m.set(group, (m.get(group) || 0) + 1), new Map),
        ([group, active]) => ({ group, active })
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

Arup Rakshit
Arup Rakshit

Reputation: 118271

You can do it as below, first filter and then group them by active value.

const groups = [{
  id: 234
}, {
  id: 423
}, {
  id: 474
}, {
  id: 864
}]

const things = [{
  id: 1,
  active: false,
  group: 234
}, {
  id: 2,
  active: true,
  group: 234
}, {
  id: 3,
  active: false,
  group: 234
}, {
  id: 4,
  active: true,
  group: 423
}, {
  id: 5,
  active: true,
  group: 423
}, {
  id: 6,
  active: false,
  group: 423
}];

const temp = things.filter(thing => {
  return groups.find(group => group.id == thing.group && thing.active)
}).reduce((mem, cur) => {
  mem[cur.group] = (mem[cur.group] || 0) + 1;
  return mem;
}, {});

const result = Object.keys(temp).map(key => ({
  'group': key,
  active: temp[key]
}));

console.log(result);

Upvotes: 1

Related Questions