James_RajKumar
James_RajKumar

Reputation: 231

How to compare elements of an array and merge based on a condition?

I have the below sample array.(original array has more than 200 elements)

var array = [
  {
    "clientid": "ID000002",
    "accesstoken": "pllALEl3TlwLL9hHP938H",
    "groupname": "ABC",
    "ancestorid": "8982857550",
    "stroyid": [
      "IGN-EXM-001-PDF",
      "IGN-EXM-002-PDF"
    ]
  }, {
    "clientid": "ID000002",
    "accesstoken": "pllALEl3TlwpHOD4aTP38H",
    "groupname": "EFG",
    "ancestorid": "4705872914",
    "stroyid": [
      "APP-ENE-FIE-CON",
      "APP-ENE-ASS-INS",
      "APP-ENE-ASS-CAR",
      "APP-ENE-MAT-REA"
    ]
  }, {
    "clientid": "ID000002",
    "accesstoken": "pllALEl3TlwLL9hHP938H",
    "groupname": "ABC",
    "ancestorid": "8982857550",
    "stroyid": [
      "IGN-EXM-001-ZIP",
      "IGN-EXM-002-ZIP"
    ]
  }
]

Condition = if (client id && ancestor id are the same then merge the storyid) so the output should be like:

[{
  "clientid": "ID000002",
  "accesstoken": "pllALEl3TlwLL9hHP938H",
  "groupname": "ABC",
  "ancestorid": "8982857550",
  "stroyid": [
    "IGN-EXM-001-PDF",
    "IGN-EXM-002-PDF",
    "IGN-EXM-001-ZIP",
    "IGN-EXM-002-ZIP"

  ]
}, {
  "clientid": "ID000002",
  "accesstoken": "pllALEl3TlwpHOD4aTP38H",
  "groupname": "EFG",
  "ancestorid": "4705872914",
  "stroyid": [
    "APP-ENE-FIE-CON",
    "APP-ENE-ASS-INS",
    "APP-ENE-ASS-CAR",
    "APP-ENE-MAT-REA"
  ]
}]

Please help me with javascript code to achieve this.

Upvotes: 4

Views: 3711

Answers (4)

Ahmad Al-Sanie
Ahmad Al-Sanie

Reputation: 3785

You can use the below to merge storyId without duplicates and then replace it with the original storyId array:

if(array[0].clientid == array[1].clientid && array[0].ancestorid == array[1].ancestorid){
var c = array[0].stroyid.concat(array[1].stroyid.filter(function (item) {
    return array[0].stroyid.indexOf(item) < 0;
}));
}

Upvotes: 1

nem035
nem035

Reputation: 35491

One way you can approach this is to iterate through your array and add results to a Map based on a unique combination for your merging condition. Something like concatenation of ids should work.

If the map already had an object at this condition as its key, we merge the current item with the value, otherwise, we add it.

One bottleneck for your code is that you also require deep merging of these objects which isn't supported natively in JavaScript and is out of the scope of this question. You can check out this SO thread.

Here's an example (I'm using the deepmerge library for the merging):

var array=[{clientid:"ID000002",accesstoken:"pllALEl3TlwLL9hHP938H",groupname:"ABC",ancestorid:"8982857550",stroyid:["IGN-EXM-001-PDF","IGN-EXM-002-PDF"]},{clientid:"ID000002",accesstoken:"pllALEl3TlwpHOD4aTP38H",groupname:"EFG",ancestorid:"4705872914",stroyid:["APP-ENE-FIE-CON","APP-ENE-ASS-INS","APP-ENE-ASS-CAR","APP-ENE-MAT-REA"]},{clientid:"ID000002",accesstoken:"pllALEl3TlwLL9hHP9n",groupname:"ABC",ancestorid:"8982857550",stroyid:["IGN-EXM-001-ZIP","IGN-EXM-002-ZIP"]}];
    
const map = new Map();
const mergeKey = ({ clientid, ancestorid }) => `${clientid}${ancestorid}`;

for (const item of array) {
  const key = mergeKey(item);
  if (map.has(key)) {
    map.set(key, deepmerge(map.get(key), item));
  } else {
    map.set(key, item);
  }
}

const merged = Array.from(map.values());
console.log(merged);
<script src="https://unpkg.com/[email protected]/index.js"></script>

ES5 version if needed:

var array=[{clientid:"ID000002",accesstoken:"pllALEl3TlwLL9hHP938H",groupname:"ABC",ancestorid:"8982857550",stroyid:["IGN-EXM-001-PDF","IGN-EXM-002-PDF"]},{clientid:"ID000002",accesstoken:"pllALEl3TlwpHOD4aTP38H",groupname:"EFG",ancestorid:"4705872914",stroyid:["APP-ENE-FIE-CON","APP-ENE-ASS-INS","APP-ENE-ASS-CAR","APP-ENE-MAT-REA"]},{clientid:"ID000002",accesstoken:"pllALEl3TlwLL9hHP9n",groupname:"ABC",ancestorid:"8982857550",stroyid:["IGN-EXM-001-ZIP","IGN-EXM-002-ZIP"]}];
    
var map = Object.create(null);
function mergeKey(item) {
  return item.clientid + item.ancestorid;
}

array.forEach(function(item) {
  var key = mergeKey(item);
  if (map[key]) {
    map[key] = deepmerge(map[key], item);
  } else {
    map[key] = item;
  }
});

var merged = Object.keys(map).map(function(key) {
  return map[key];
});
console.log(merged);
<script src="https://unpkg.com/[email protected]/index.js"></script>

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386680

With plain Javascript, you could use a hash table as closure for grouping with clientid and ancestorid.

stroyid gets filtered for unique values.

var array = [{ clientid: "ID000002", accesstoken: "pllALEl3TlwLL9hHP938H", groupname: "ABC", ancestorid: "8982857550", stroyid: ["IGN-EXM-001-PDF", "IGN-EXM-002-PDF", "dupe"] }, { clientid: "ID000002", accesstoken: "pllALEl3TlwpHOD4aTP38H", groupname: "EFG", ancestorid: "4705872914", stroyid: ["APP-ENE-FIE-CON", "APP-ENE-ASS-INS", "APP-ENE-ASS-CAR", "APP-ENE-MAT-REA"] }, { clientid: "ID000002", accesstoken: "pllALEl3TlwLL9hHP9n", groupname: "ABC", ancestorid: "8982857550", stroyid: ["IGN-EXM-001-ZIP", "IGN-EXM-002-ZIP", "dupe"] }],
    result = array.reduce(function (hash) {
        return function (r, a) {
            var key = [a.clientid, a.ancestorid].join('|');
            if (!hash[key]) {
                hash[key] = { clientid: a.clientid, accesstoken: a.accesstoken, groupname: a.groupname, ancestorid: a.ancestorid, stroyid: a.stroyid };
                return r.concat(hash[key]);
            }
            hash[key].stroyid = hash[key].stroyid.concat(a.stroyid).filter(function (temp) {
                return function (a) {
                    return !temp[a] && (temp[a] = true);
                };
            }(Object.create(null)));
            return r;
        };
    }(Object.create(null)), []);
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 3

user5183133
user5183133

Reputation:

const myArray = [
  { clientid: 1, ancestorid: 1, stroyid: ['a', 'b', 'c'] },
  { clientid: 1, ancestorid: 1, stroyid: ['a', 'b', 'd', 'e'] },
];

const newArray = myArray.reduce((newArray, entry) => {
  // Find if there is a duplicate in the new array
  const duplicate = newArray.find(newEntry => (
    entry.clientid === newEntry.clientid && entry.ancestorid === newEntry.ancestorid
  ));

  // If there is a duplicate, merge their stroyids
  if (duplicate) {
    const cleanIDs = entry.stroyid.filter(id => !duplicate.stroyid.includes(id));
    duplicate.stroyid = duplicate.stroyid.concat(cleanIDs);
  }
  else newArray.push(entry); // Else, add the entire entry

  return newArray;
}, []);

console.log(newArray);

Upvotes: 1

Related Questions