1

I want to merge value to array if it have a same id. I have one array of objects like this.

[ 
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Rosie',
 },
 { 
   id: 'Jane',
   type: 'human',
   favorite: null,
 },
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Lisa',
 },
 { 
   id: 'Steve',
   type: 'hero',
   favorite: 'Jennie',
 },
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Jisoo',
 },
]

and I want to merge key favorite from string to array. I want output like this

[ 
 { 
   id: 'Tony',
   type: 'hero',
   favorite: ['Rosie', 'Lisa', 'Jisoo'],
 },
 { 
   id: 'Jane',
   type: 'human',
   favorite: null,
 },
 { 
   id: 'Steve',
   type: 'hero',
   favorite: ['Jennie'],
 } 

and i try to write code like this: (from: Sum similar keys in an array of objects )

var obj = [
    {
      id: 'Tony',
      type: 'hero',
      favorite: 'Rosie',
    },
    {
      id: 'Jane',
      type: 'human',
      favorite: null,
    },
    {
      id: 'Tony',
      type: 'hero',
      favorite: 'Lisa',
    },
    {
      id: 'Steve',
      type: 'hero',
      favorite: 'Jennie',
    },
    {
      id: 'Tony',
      type: 'hero',
      favorite: 'Jisoo',
    },
  ];

  var holder = {};
  const ar = []
  obj.forEach(function (d) {
    if (holder.hasOwnProperty(d.id)) {
      holder[d.id] = ar.push(holder[d.id] + d.favorite);
    } else {
      holder[d.id] = d.favorite;
    }
  });

  var obj2 = [];

  for (var prop in holder) {
    obj2.push({ name: prop, favorite: holder[prop] });
  }

  console.log(obj2);

but out put is

[ { name: 'Tony', favorite: 2 },
  { name: 'Jane', favorite: null },
  { name: 'Steve', favorite: 'Jennie' } ]

How can i do this ?

2
  • What have you done so far? Isnt jane's favorite should be [null]? Commented May 16, 2019 at 4:00
  • i try to write code from stackoverflow.com/questions/24444738/…, and Jane dont have a favourite Commented May 16, 2019 at 4:05

5 Answers 5

6

You can do this with a single Array.reduce and would most likely be the most simple and performant approach:

var data = [ { id: 'Tony', type: 'hero', favorite: 'Rosie', }, { id: 'Jane', type: 'human', favorite: null, }, { id: 'Tony', type: 'hero', favorite: 'Lisa', }, { id: 'Steve', type: 'hero', favorite: 'Jennie', }, { id: 'Tony', type: 'hero', favorite: 'Jisoo', }, ]

let result = data.reduce((r, {id,type,favorite}) => {
  r[id] = r[id] || {id, type, favorite: []}
  r[id].favorite.push(favorite)
  return r
}, {})

console.log(Object.values(result))

The idea is to "group by" the id and then keep pushing to the favorites array on each iteration.

For ES5 you can do it in similar fashion:

var data = [ { id: 'Tony', type: 'hero', favorite: 'Rosie', }, { id: 'Jane', type: 'human', favorite: null, }, { id: 'Tony', type: 'hero', favorite: 'Lisa', }, { id: 'Steve', type: 'hero', favorite: 'Jennie', }, { id: 'Tony', type: 'hero', favorite: 'Jisoo', }, ]

let result = data.reduce(function(r, c){
   r[c.id] = r[c.id] || {id: c.id, type: c.type, favorite: []}
   r[c.id].favorite.push(c.favorite)
   return r
}, {})

console.log(Object.values(result))

There really is no need for lodash to achieve this.

Sign up to request clarification or add additional context in comments.

Comments

0

Group by the id with _.group(), and then merge each group using _.map() and _.mergeWith(), and collect favorite to an array:

const data = [{"id":"Tony","type":"hero","favorite":"Rosie"},{"id":"Jane","type":"human","favorite":null},{"id":"Tony","type":"hero","favorite":"Lisa"},{"id":"Steve","type":"hero","favorite":"Jennie"},{"id":"Tony","type":"hero","favorite":"Jisoo"}]

const result = _(data)
  .groupBy('id')
  .map(g => _.mergeWith({}, ...g, (o, s, k) => {
    if(k !== 'favorite') return // non favorite key are not collected to an array
    
    if(_.isNil(s)) return o // don't add null or undefined to array
    
    return [].concat(o || [], s) // concat other values to array
  }))
  .value()
  
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

Comments

0

Use map and Set to get this result.

First we create a new unique Set using the id field.

We seed a new new array from this and call the map method.

const arr = [ 
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Rosie',
 },
 { 
   id: 'Jane',
   type: 'human',
   favorite: null,
 },
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Lisa',
 },
 { 
   id: 'Steve',
   type: 'hero',
   favorite: 'Jennie',
 },
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Jisoo',
 },
];

const masterArr = [...new Set(arr.map((e) => e.id))].map(a => ({
  id: a,
  type: arr.find(x => x.id === a).type,
  favorites: arr.filter(x => x.id === a).map(y => y.favorite)
}));

console.log(masterArr);

Comments

0

You can use reduce on the array.

const arr = [ 
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Rosie',
 },
 { 
   id: 'Jane',
   type: 'human',
   favorite: null,
 },
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Lisa',
 },
 { 
   id: 'Steve',
   type: 'hero',
   favorite: 'Jennie',
 },
 { 
   id: 'Tony',
   type: 'hero',
   favorite: 'Jisoo',
 },
]
const out = arr.reduce((result, el)=> {
    const id = result.findIndex(e => e.id ===el.id)

    if(id> -1){
        result[id] = {...result[id], favorite: [...result[id].favorite, el.favorite]}
    } else {result.push({...el, favorite: [el.favorite].filter(x => x) })}
    return result
}, [])
console.log(out)

Comments

0

Just loop over the array and construct a new array after converting favorite attribute into an array, then for next elements with the same id, push to favorite array

let users = [{id: 'Tony', type: 'hero', favorite: 'Rosie',}, {id: 'Jane', type: 'human', favorite: null,}, {id: 'Tony', type: 'hero', favorite: 'Lisa',}, {id: 'Steve', type: 'hero', favorite: 'Jennie',}, {id: 'Tony', type: 'hero', favorite: 'Jisoo',},];

// To combine friends of the same user in an array at property friendNames
let merged = {};
for (let user of users) {
    if (typeof merged[user.id] === 'undefined') {
        user.favorite = [user.favorite];
        merged[user.id] = user;
    } else {
        merged[user.id].favorite.push(user.favorite)
    }
}

console.log(Object.values(merged));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.