0

I have seen some questions that might look similar but none is the solution in my case. I want to regroup and recreate my array the way that it is arranged or grouped based on one of my values(age). I want to have all data of the same "age" in one place. So here is my sample array:

[
  {
    "age": 15,
    "person": {
      name: 'John',
      hobby: 'ski'
    },
  },
  {
    "age": 23,
    "person": {
      name: 'Suzi',
      hobby: 'golf'
    },
  },
  {
    "age": 23,
    "person": {
      name: 'Joe',
      hobby: 'books'
    }
  },{
    "age": 25,
    "person": {
      name: 'Rosi',
      hobby: 'books'
    }
  },{
    "age": 15,
    "person": {
      name: 'Gary',
      hobby: 'books'
    }
  },
  {
    "age": 23,
    "person": {
      name: 'Kane',
      hobby: 'books'
    }
  }
]

And I need to have an array that kind of have age as a key and person as value, so each key could have multiple values meaning the value will kind of be an array itself. I have read this and this questions and many more but they were not exactly the same. I feel like I need to use reduce to count duplicate ages and then filter it based on that but how do I get the values of those ages?

EIDT:

Sorry for not being clear:

This is what I need:

{ 
  23: [
    { name: 'Suzi', hoby: 'golf' }, 
    { name: 'Joe', hobby: 'books'}
  ], 
 15: [
    { name: 'Gary', hobby: 'books' }
  ] ,
  .
  .
  .
}
azad6026
  • 139
  • 1
  • 3
  • 11
  • 1
    you might want to look at JavaScript a little closer. I'd suggest looking at the MDN for Array and Object since it seems like you have a small misunderstanding of how the data types work in JS. Beyond that the algorithm you're asking is a simple `Array.prototype.reduce()`(also known as `Array#reduce()`) that will take the age, and insert the values. Of course this means you'll want to check for the existence of duplicate or similar data, but if you're not worried about that a reduce will be more than enough – Robert Mennell Oct 25 '18 at 22:28
  • 1
    Also you're going to want to think a little closer about your question. In it's current form it'll get a bunch of down votes because the question is ill formed and hard to figure out what you want. It should be more along the lines of `How do I transform an array to hold data based on a value in the data?` – Robert Mennell Oct 25 '18 at 22:39
  • Thank you @RobertMennell. You are absolutely right. I changed the title and will figure it out with Reduce. Voted for your comments. Thanks. – azad6026 Oct 25 '18 at 22:51
  • Glad I could help! – Robert Mennell Oct 25 '18 at 23:12
  • You certainly did.Cheers. – azad6026 Oct 25 '18 at 23:31

2 Answers2

1

You're actually going to want to reduce, not filter. Filtering an Array means to remove elements and place the kept elements into a new container. Reducing an array means to transform it into a single value in a new container. Mapping an array means to transform every value in place to a new container. Since you want to change how the data is represented that's a Reduction, from one form to another more condensed form.

Assume your Array of values is stored in let people = [...]

let peopleByAge = people.reduce(function (accumulator, value, index, array){
  // The first time through accumulator is the passed extra Object after this function
  // See the MDN for Array.prototype.reduce() for more information
  if (accumulator[value.age] == undefined){
    accumulator[value.age] = [];
  }
  accumulator[value.age].push(value);
  return accumulator
}, {})

console.log(peopleByAge) // { 23: [{ age: 23, name: ..., hobby: ...}, ...], 13: [...], ...}

You can find the MDN article for Array#reduce() here

Robert Mennell
  • 1,954
  • 11
  • 24
0

Thanks to @RobertMennell who patiently answered me and I voted as answer. But I just wanted to write my version which MDN had a great example of. It is a longer version assuming the people is the array name:

const groupedByvalue = 'age';
const groupedArray = people;
const  groupBy = (peopleArray, value) => {
  return peopleArray.reduce((acc, obj) => {
     const key = obj[value];
     if (!acc[key]) {
     acc[key] = [];
    }
    acc[key].push(obj);
    return acc;
  }, {});
}
console.log(groupBy(groupedArray,groupedByvalue));

Update:

More polished using ternary operator:

const groupedByvalue = 'age';
const groupedArray = people;
const  groupBy = (peopleArray, value) => {
  return peopleArray.reduce((acc, obj) => {
     const key = obj[value];
     (!acc[key]) ? (acc[key] = []) : (acc[key].push(obj))
     return acc;
  }, {});
}
console.log(groupBy(groupedArray,groupedByvalue));
azad6026
  • 139
  • 1
  • 3
  • 11
  • your ternary is wrong. It dumps the first value into the ether. Try `acc[key] ? (acc[key] = [obj]) : (acc[key].push(obj))` – Robert Mennell Oct 26 '18 at 01:09
  • of course I would rather not use a ternary here as it's more confusing since it does either an assignment or a method call. You should instead make it an optional assignement `acc[key] = acc[key] || []; acc[key].push(obj);` – Robert Mennell Oct 26 '18 at 01:11
  • Thanks @RobertMennell. Yes in these cases I shouldn't. Just wanted to make it shorter otherwise all good. Cheers. – azad6026 Oct 26 '18 at 02:57
  • Also "Cannot read property 'push' of undefined" is what I get when I used your ternary. Not sure why? – azad6026 Oct 26 '18 at 03:00
  • Whoops forgot a negation. `!acc[key] ? (acc[key] = [obj]) : (acc[key].push(obj))` – Robert Mennell Oct 26 '18 at 03:01
  • I thought you did that intentionally I wondered why :) ? Great. – azad6026 Oct 26 '18 at 03:19