arunmmanoharan
arunmmanoharan

Reputation: 2675

Check if a merged array has item from two arrays and update the merged array JS

I have two arrays. I merge it and remove duplicates. Merging is done by taking into consideration all keys of the arrays (all key values in the object in array 1 must match with those in array 2).

var result1 = [{
    name: 'Sandra',
    email: '[email protected]'
  },
  {
    name: 'John',
    email: '[email protected]'
  },
  {
    name: 'Peter',
    email: '[email protected]'
  },
  {
    name: 'Bobby',
    email: '[email protected]'
  },
  {
    name: 'Arun',
    email: '[email protected]'
  },
];

var result2 = [{
    name: 'John',
    email: '[email protected]'
  },
  {
    name: 'Bobby',
    email: '[email protected]'
  },
  {
    name: 'Arun',
    email: '[email protected]'
  }
];

var result= _.uniqWith(_.concat(result1, result2), _.isEqual)

Now I need to check each item of merged array with each item of array1 and array2 and update the merged array if they are present or not.

So my end result should be like this.

var result = [{
    name: 'Sandra',
    email: '[email protected]',
    presentInA: true,
    presentInB: false
  },
  {
    name: 'John',
    email: '[email protected]',
    presentInA: true,
    presentInB: true
  },
  {
    name: 'Peter',
    email: '[email protected]',
    presentInA: true,
    presentInB: false
  },
  {
    name: 'Bobby',
    email: '[email protected]',
    presentInA: true,
    presentInB: true
  },
  {
    name: 'Arun',
    email: '[email protected]',
    presentInA: false,
    presentInB: true
  },
  {
    name: 'Arun',
    email: '[email protected]',
    presentInA: true,
    presentInB: false
  }
];

How do I go about doing this in the best way? I think I can do it with iterating through all 3 arrays, but its a bad way of doing that.

Please advice.

Upvotes: 1

Views: 147

Answers (3)

Jonas Wilms
Jonas Wilms

Reputation: 138437

You could use a hashtable for finding & merging dupes:

 // Merges objects with the same name and email, sets the [arrName] property of the merged object to true
 // also takes an optional settings object for chaining
 function merge(arr, arrName, { hash = {}, result = [] } = {}) {
   for(const { name, email } of arr) {
      // Build up a hopefully unique key
     const key = name + "@" + email;
     // If its not in the hash yet, add it to the hash and the result
     if(!hash[key]) 
        result.push(hash[key] = { name, email });
     // then set the key
     hash[key][arrName] = true;
  }
  // allow chaining by exposing both hash and result
  return { hash, result, merge: (arr, arrName) => merge(arr, arrName, { hash, result }) };
 }

That could be used as:

 const { result } = merge(result1, "presentInA").merge(result2, "presentInB");

That is O(n) but assumes that emails do not contain two @s.

Upvotes: 1

German Burgardt
German Burgardt

Reputation: 385

You can do something like this

result.map(
    per => ({
        name: per.name,
        email: per.email,
        presentInA: _.find(
            result1, (o) => o.nombre === per.nombre && o.email === per.email
        ) ? true : false,
        presentInB: _.find(
            result2, (o) => o.nombre === per.nombre && o.email === per.email
        ) ? true : false,
    })
)

Upvotes: 2

lealceldeiro
lealceldeiro

Reputation: 14968

You could iterate over result and use _.some in order to check whether each object inside it is in result1 and result2 (and set the corresponding properties presentInA and presentInB). Something like this:

_.forEach(result, (obj) => {
   let presentInA = _.some(result1, obj);
   let presentInB = _.some(result2, obj);
   obj.presentInA = presentInA;
   obj.presentInB = presentInB;
});

var result1 = [{
    name: 'Sandra',
    email: '[email protected]'
  },
  {
    name: 'John',
    email: '[email protected]'
  },
  {
    name: 'Peter',
    email: '[email protected]'
  },
  {
    name: 'Bobby',
    email: '[email protected]'
  },
];

var result2 = [{
    name: 'John',
    email: '[email protected]'
  },
  {
    name: 'Bobby',
    email: '[email protected]'
  },
  {
    name: 'Arun',
    email: '[email protected]'
  }
];

var result = _.uniqWith(_.concat(result1, result2), _.isEqual);

_.forEach(result, (obj) => {
   let presentInA = _.some(result1, obj);
   let presentInB = _.some(result2, obj);
   obj.presentInA = presentInA;
   obj.presentInB = presentInB;
});

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

Upvotes: 2

Related Questions