-1

I have an array of objects with nested object, as shown below:

[
  {
    "metric1": 4.1,
    "addons": {
      "call_uuid_1": "13d1e097-0363-4a81-b9e4-85c6a770cdb2",
      "ThisDN_1": "50002",
      "call_uuid": "13d1e097-0363-4a81-b9e4-85c6a770cdb4",
      "ThisDN": "50004"
    }
  },
  {
    "metric2": -12345.123412341234,
    "addons": {
      "call_uuid_2": "13d1e097-0363-4a81-b9e4-85c6a770cdb3",
      "ThisDN_2": "50003",
      "call_uuid": "13d1e097-0363-4a81-b9e4-85c6a770cdb4",
      "ThisDN": "50004"
    }
  },
  {
    "metric3": -2345.123412341234,
    "addons": {
      "call_uuid_1": "13d1e097-0363-4a81-b9e4-85c6a770cdb2",
      "ThisDN_1": "50002",
      "call_uuid": "13d1e097-0363-4a81-b9e4-85c6a770cdb4",
      "ThisDN": "50004"
    }
  },
  {
    "metric4": -345.12341234123414,
    "addons": {
      "call_uuid_2": "13d1e097-0363-4a81-b9e4-85c6a770cdb3",
      "ThisDN_2": "50003",
      "call_uuid": "13d1e097-0363-4a81-b9e4-85c6a770cdb4",
      "ThisDN": "50004"
    }
  }
]

I want to merge some of the array objects with the same nested object addons, so that the previous array becomes:

[
  {
    "metric1": 4.1,
    "metric3": -2345.123412341234,
    "addons": {
      "call_uuid_1
": "13d1e097-0363-4a81-b9e4-85c6a770cdb2",
      "ThisDN_1": "50002",
      "call_uuid": "13d1e097-0363-4a81-b9e4-85c6a770cdb4",
      "ThisDN": "50004"
    }
  },
  {
    "metric2": -12345.123412341234,
    "metric4": -345.12341234123414,
    "addons": {
      "call_uuid_2": "13d1e097-0363-4a81-b9e4-85c6a770cdb3",
      "ThisDN_2": "50003",
      "call_uuid": "13d1e097-0363-4a81-b9e4-85c6a770cdb4",
      "ThisDN": "50004"
    }
  }
]

Are there any ways to do this?

Ken Tsoi
  • 1,195
  • 1
  • 17
  • 37
  • 1
    `call_uuid_l`("l" instead of "1") is this a typo, or are keys not the same as each other? – yes sir Jun 02 '22 at 05:51
  • Why would you not want to use `lodash`, It's treeshakable and its core build is currently only [~4kb](https://lodash.com/)? – Dane Brouwer Jun 02 '22 at 10:56
  • 1
    @yessir it was a typo, fixed now. – Ken Tsoi Jun 02 '22 at 14:00
  • @DaneBrouwer I had thought that it has vulnerabilities, but just found that the latest version(v4,17.21) is OK (https://snyk.io/advisor/npm-package/lodash). A bit pity that it is not actively maintained. – Ken Tsoi Jun 02 '22 at 14:06

2 Answers2

1

You can use JSON.stringify to look for equality in the addons object and then merge your objects. Like this:

const array = [
  {
    "metric1": 4.1,
    "addons": {
      "call_uuid_1": "13d1e097-0363-4a81-b9e4-85c6a770cdb2",
      "ThisDN_1": "50002",
      "call_uuid": "13d1e097-0363-4a81-b9e4-85c6a770cdb4",
      "ThisDN": "50004"
    }
  },
  {
    "metric2": -12345.123412341234,
    "addons": {
      "call_uuid_2": "13d1e097-0363-4a81-b9e4-85c6a770cdb3",
      "ThisDN_2": "50003",
      "call_uuid": "13d1e097-0363-4a81-b9e4-85c6a770cdb4",
      "ThisDN": "50004"
    }
  },
  {
    "metric3": -2345.123412341234,
    "addons": {
      "call_uuid_1": "13d1e097-0363-4a81-b9e4-85c6a770cdb2",
      "ThisDN_1": "50002",
      "call_uuid": "13d1e097-0363-4a81-b9e4-85c6a770cdb4",
      "ThisDN": "50004"
    }
  },
  {
    "metric4": -345.12341234123414,
    "addons": {
      "call_uuid_2": "13d1e097-0363-4a81-b9e4-85c6a770cdb3",
      "ThisDN_2": "50003",
      "call_uuid": "13d1e097-0363-4a81-b9e4-85c6a770cdb4",
      "ThisDN": "50004"
    }
  }
];

const mergedArray = [];
const addonsToIndexMap = {};

array.forEach(item => {
 const stringifyAddon = JSON.stringify(item.addons);    
 let indexInTheMap = addonsToIndexMap[stringifyAddon];
 if(indexInTheMap !== undefined) {
   mergedArray[indexInTheMap] = {...mergedArray[indexInTheMap], ...item};
 } else {
   mergedArray.push(item);
   addonsToIndexMap[stringifyAddon] = mergedArray.length - 1;
 }
});
console.log(mergedArray);

The use of addonsToIndexMap is just for optimization purposes. Note: This method only works if the order of keys within the addon objects is the same. Also, I rectified the input in my program to update the key call_uuid_l with call_uuid_1 to get the expected output, as mentioned in the comments. Please modify it accordingly.

Charchit Kapoor
  • 8,934
  • 2
  • 8
  • 24
  • Thanks @charchitkapoor for the effort. I finally use `lodash` after finding out that there is no other alternation. (sorry for that, I have removed the restriction from the post. – Ken Tsoi Jun 02 '22 at 19:43
1

If the array has more than one element with the same addons object, you can delete the first one's addons object and then merge it with the others.

for (let i = 0; i < arr.length; i++) {
  for (let j = i + 1; j < arr.length; j++) {
    if (JSON.stringify(arr[i]["addons"]) === JSON.stringify(arr[j]["addons"])) {
      delete arr[i]["addons"];
      Object.assign(arr[i], arr[j]);
      arr.splice(j, 1);
      j -= 1;
    }
  }
}

Output:

[
  {
    metric1: 4.1,
    metric3: -2345.123412341234,
    addons: {
      call_uuid_1: '13d1e097-0363-4a81-b9e4-85c6a770cdb2',
      ThisDN_1: '50002',
      call_uuid: '13d1e097-0363-4a81-b9e4-85c6a770cdb4',
      ThisDN: '50004'
    }
  },
  {
    metric2: -12345.123412341234,
    metric4: -345.12341234123414,
    addons: {
      call_uuid_2: '13d1e097-0363-4a81-b9e4-85c6a770cdb3',
      ThisDN_2: '50003',
      call_uuid: '13d1e097-0363-4a81-b9e4-85c6a770cdb4',
      ThisDN: '50004'
    }
  }
]
yes sir
  • 220
  • 2
  • 8
  • 1
    Thanks @yessir, straight forward one, I optimize a little bit by changing the 2nd for loop to start from i+1. Also I use `lodash` finally after finding out that there is no other alternation. (sorry for that, I have removed the restriction from the post. – Ken Tsoi Jun 02 '22 at 19:40
  • @KenTsoi Add `j -= 1` at the end of the `if` block if you'll use 'i+1', or it doesn't work if the array has more than four objects. – yes sir Jun 03 '22 at 09:10
  • 1
    Good catch for the `j-=1`, but why it doesn't work if the array has more than 4 objects? – Ken Tsoi Jun 03 '22 at 18:32
  • 1
    BTW, I am using `lodash.isequal`(https://www.npmjs.com/package/lodash.isequal) to avoid loading the whole lodash package. – Ken Tsoi Jun 03 '22 at 18:38
  • @KenTsoi `splice()` remove elements from the array, so if you don't use the `j -= 1` index will continue to increase while the array length decreases. – yes sir Jun 03 '22 at 18:41
  • 1
    yes I understand that, but why 4 objects? – Ken Tsoi Jun 03 '22 at 18:49
  • My bad, it's not about 4 objects. Not works if there are more than 2 elements(at least 3) in a row with the same `addons` object. Because it skips the next object. When you're checking the 4th array element if it's the same as another one you will splice it. Now array length decreased while your `j` increased. You have to check the same index again because the 5th element is now the 4th. – yes sir Jun 03 '22 at 19:08