Looking to group array by values in the sub array

Viewed 59

Trying to parse one data set that has a bunch of the same "secondaryIDs" in way that i can group and iterate through them together.

In english what im trying to do is "select a unique group of all items where the value of field is unique "

'use strict';

const data = [{
    Group: 'A',
    Name: 'SD'
}, {
    Group: 'B',
    Name: 'FI'
}, {
    Group: 'A',
    Name: 'MM'
}, {
    Group: 'B',
    Name: 'CO'
}];

let unique = [...new Set(data.map(item => item.Group))];
console.log(unique);

Which gives ["A"],["B"]

but what im looking for is

{
  A: [ "SD","MM" ],
  B: [ "FI","CO" ],
}
6 Answers

You can also reduce your array to the grouped object (keyed by Group values):

const data = [{
  Group: 'A',
  Name: 'SD'
}, {
  Group: 'B',
  Name: 'FI'
}, {
  Group: 'A',
  Name: 'MM'
}, {
  Group: 'B',
  Name: 'CO'
}];

const grouped = data.reduce((a, {Group, Name}) => {
  if (!(Group in a)) a[Group] = [Name];
  else a[Group].push(Name);
  return a;
}, {});

console.log(grouped);

For this, I would use array.reduce instead of array.map because what you're actually hoping to return is a new value, not a modified array, the reduce method is perfect when you want to literally reduce the array into a single output value, in your case an object of unique groups. Maybe try something like this:

let unique = data.reduce((acc, { Group, Name }) => {
  if (!(acc.hasOwnProperty(Group))) {
    acc[Group] = [Name];
  } else {
    acc[Group].push(Name);
  }; 
  return acc;
}, {});

I've also added a pen for this at: https://codepen.io/anon/pen/BGpgdz?editors=1011 so you can see this working.

Hope this helps!

can do something like..

const map = {};
data.forEach( d => {
    if( map[d.Group] ) {
        map[d.Group].push(d.Name);
    } else {
        map[d.Group] = [d.Name];
    }
})
console.log(map)

I think the easiest way to achieve this would be to use Array.prototype.reduce method to create an object that maps unique Group names to arrays that contain Names. You can supply an empty object literal as your initial reduce accumulator:

const data = [{
  Group: 'A',
  Name: 'SD'
}, {
  Group: 'B',
  Name: 'FI'
}, {
  Group: 'A',
  Name: 'MM'
}, {
  Group: 'B',
  Name: 'CO'
}];

var namesByGroup = data.reduce((map, el) => {
  map[el.Group] ? map[el.Group].push(el.Name) : map[el.Group] = [el.Name];
  return map;
}, {});

console.log(namesByGroup);

If you're interested in a functional approach, here is a solution using Ramda:

const group =
  R.pipe(
    R.groupBy(R.prop('Group')),
    R.map(R.map(R.prop('Name'))));

console.log(
  group([
    {Group: 'A', Name: 'SD'},
    {Group: 'B', Name: 'FI'},
    {Group: 'A', Name: 'MM'},
    {Group: 'B', Name: 'CO'}])
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

can also be done using forEach

const data = [{
 Group: 'A',
 Name: 'SD'
}, {
 Group: 'B',
 Name: 'FI'
}, {
 Group: 'A',
 Name: 'MM'
}, {
 Group: 'B',
 Name: 'CO'
}];

const somefunction = (data) => {
let arr = {}
data.forEach( ({Group, Name}) => {
  Group in arr ?  arr[Group].push(Name) : arr[Group] = [Name]
})
return arr;
}

console.log(somefunction(data))

Related