0

I'm trying to merge objects in an array with the same id without overriding different value properties.

var arr = [{
  Messages: { count: 1 },
  Account: { key: 'TEST' },
  id: 179,
  Contact:
  {
    firstName: 'The Postman',
    lastName: 'Team'
  },
  Tags: { name: 'forums', color: '#0091EA' }
},
{
  Messages: { count: 1 },
  Account: { key: 'TEST' },
  id: 179,
  Contact:
  {
    firstName: 'The Postman',
    lastName: 'Team'
  },
  Tags: { name: 'defective', color: '#0091EA' }
}];

var tags = [];
for(var i=0; i<arr.length; i++){
  tags = tags.concat(arr[i].Tags);
}

var result = arr[0];
result.Tags = tags;
 
console.log(result);

My goal is is to have the following object:

var obj =
{ Messages: { count: 1 }, 
  Account: { key: "TEST" }, 
  id: 179, 
  Contact: { firstName: "The Postman", lastName: "Team" }, 
  Tags: [{ name: "forums", color: "#0091EA" }, { name: "defective", color: "#0091EA" }] 
};

I've created a fiddle where I managed to get the desired output, but I'm sure there is a better way to do it. http://jsfiddle.net/18mLhx7j/1/

UPDATE

Based on the answer posted by @Harun Yilmaz I was able to accomplish the same result using Lodash reduce. I just wonder if it's a valid alternative to what he posted.

var arr = [
{ Messages: { count: 1 }, 
  Account: { key: "TEST" }, 
  id: 179, 
  Contact: { firstName: "The Postman", lastName: "Team" }, 
  Tags: { name: "forums", color: "#0091EA" } },
{ Messages: { count: 1 }, 
  Account: { key: "TEST" }, 
  id: 179, 
  Contact: { firstName: "The Postman", lastName: "Team" }, 
  Tags: { name: "defective", color: "#0091EA" } }
];

var interactions =_.reduce(arr, function(acc, cur) { 
    for (let i =0; i < Object.keys(cur).length; i++) {
        let key = Object.keys(cur)[i];
        if (!acc[key]) {
            acc[key] = cur[key];
        } else if (acc[key] && !_.isArray(acc[key]) && !_.isEqual(acc[key], cur[key])) {
            var obj = [];
            obj.push(acc[key]);
            obj.push(cur[key]);
            acc[key] = obj;
        } else if (acc[key] && _.isArray(acc[key])) {
            acc[key].push(cur[key]);
        }
    }
return acc;
}, {});

console.log(interactions);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

4
  • Is it always the case that only Tags will be different and other properties will always be same? Commented Sep 26, 2019 at 12:49
  • I see two ways. First, you take a set, which can take duplicate object. Second, you change the equals() method of your object in order to take more than the id into account Commented Sep 26, 2019 at 12:50
  • How do I create a runnable stack snippet? Commented Sep 26, 2019 at 12:51
  • @amrendersingh it is at the moment, but it may change in the future Commented Sep 26, 2019 at 12:54

1 Answer 1

2

You can use Array.reduce() to have a final object and spread operator as following

var arr = [
{ Messages: { count: 1 }, 
  Account: { key: "TEST" }, 
  id: 179, 
  Contact: { firstName: "The Postman", lastName: "Team" }, 
  Tags: { name: "forums", color: "#0091EA" } },
{ Messages: { count: 1 }, 
  Account: { key: "TEST" }, 
  id: 179, 
  Contact: { firstName: "The Postman", lastName: "Team" }, 
  Tags: { name: "defective", color: "#0091EA" } }
];

const finalArr = arr.reduce((acc, cur) => {
 const {Tags,...Rest} = cur;
 
 acc.Tags.push(Tags);
 
 acc = {
  ...Rest,
  Tags: acc.Tags
 };
 
 
 return acc;

},{Tags:[]});
// ^^ initial object

console.log(finalArr);

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

3 Comments

Thank you, can you provide also a non ES6 alternative?
What if my array has multiple ids?
@amrendersingh The last id will overwrite the value.

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.