Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using .reduce() on an a list of objects

Tags:

javascript

I have this sample data set:

let list = [
  {'first': 'morgan', 'id': 1},
  {'first': 'eric', 'id': 1},
  {'first': 'brian', 'id': 2 },
  {'first': 'derek', 'id' : 2},
  {'first': 'courtney', 'id': 3},
  {'first': 'eric', 'id': 4},
  {'first': 'jon', 'id':4},
]

I am trying to end up with this:

[[1, [morgan, eric]], [2, [brian, derek]], [3, [courtney]], [4, [eric, jon]]

I am using the .reduce() function to map over the list. However, I'm somewhat stuck.

I got this working:

let b = list.reduce((final_list, new_item) => {
  x = final_list.concat([[new_item.id, [new_item.first]]])
  return x
}, [])

However, that flattens out the list into a list of lists of lists, but doesn't combine names that share a similar id.

I tried using .map() the code below does not work

I tried to map over the final_list (which is a list of [id, [names]] looking to see if the id of the new_item exists in the smaller_list and then add new_item.first to the smaller_list[1] (which should be the list of names).

Is this the right approach?

let b = list.reduce((final_list, new_item) => {
  final_list.map((smaller_list) => {
    if (smaller_list.indexOf((new_item.id)) >=0) {
      smaller_list[1].concat(new_item.first)
      // not sure what to do here...
    } else {
        // not sure what to do here either...
    }

  })
  x = final_list.concat([[item.id, [item.first]]])
  return x
}, [])
like image 316
Morgan Allen Avatar asked Dec 24 '22 16:12

Morgan Allen


2 Answers

In my approach, i'm using reduce to create a sparse array with the index as the list id. I then use Object.values to squash it down.

let list = [
  {'first': 'morgan', 'id': 1},
  {'first': 'eric', 'id': 1},
  {'first': 'brian', 'id': 2 },
  {'first': 'derek', 'id' : 2},
  {'first': 'courtney', 'id': 3},
  {'first': 'eric', 'id': 4},
  {'first': 'jon', 'id':4}
];

let result = list.reduce( (acc, item, index) => {
  if(acc[item.id]){
  	acc[item.id][1].push(item.first);
  } else {
  	acc[item.id] = [item.id, [item.first]];
  }
  return acc;
}, []);

console.log(Object.values(result));
like image 118
derp Avatar answered Jan 02 '23 18:01

derp


Try first creating a map of IDs to names, then map that into your final array, eg

let list = [
  {'first': 'morgan', 'id': 1},
  {'first': 'eric', 'id': 1},
  {'first': 'brian', 'id': 2 },
  {'first': 'derek', 'id' : 2},
  {'first': 'courtney', 'id': 3},
  {'first': 'eric', 'id': 4},
  {'first': 'jon', 'id':4},
]

const idMap = list.reduce((map, item) => {
  if (Array.isArray(map[item.id])) {
    map[item.id].push(item.first)
  } else {
    map[item.id] = [item.first]
  }
  return map
}, {})

const b = Object.keys(idMap).map(id => [parseInt(id), idMap[id]])
console.info(JSON.stringify(b))
like image 23
Phil Avatar answered Jan 02 '23 18:01

Phil