1

I have two array of objects.I just want to check whenever we get the first match in other array of objects,It will return first match object of array.I want only return first match,not want all the match.I am unable to break map after first match.

Example 1:-

var array1 = [{name:'Ram',lastname:'kumar'},{name:'Shyam',lastname:'kumar'},{name:'Mohan',lastname:'kumar'},{name:'Amit',lastname:'kumar'}];
var array2 = [{name:'Anil',lastname:'kumar'},{name:'Shyam',lastname:'kumar'},{name:'Mohan',lastname:'kumar'},{name:'Anjali',lastname:'kumari'}];

check array2 exist in array1 if object of array2 find in array1 then It will return only first match of array2.

output: [{name:'Shyam',lastname:'kumar'}]

Example 2 :-

var array1 = [{name:'Ram',lastname:'kumar'},{name:'Shyam',lastname:'kumar'},{name:'Mohan',lastname:'kumar'},{name:'Amit',lastname:'kumar'}];
var array2 = [{name:'Anil',lastname:'kumar'},{name:'Arti',lastname:'kumari'},{name:'Mohan',lastname:'kumar'},{name:'Anjali',lastname:'kumari'}];

output : [{name:'Mohan',lastname:'kumar'}]

//code

  var a = [{name:'Ram',lastname:'kumar'},{name:'Shyam',lastname:'kumar'},{name:'Mohan',lastname:'kumar'},{name:'Amit',lastname:'kumar'}];
    var b = [{name:'Anil',lastname:'kumar'},{name:'Shyam',lastname:'kumar'},{name:'Mohan',lastname:'kumar'},{name:'Anjali',lastname:'kumari'}];
    var c = [];

    b.forEach(function(user) {
      var exists = false;
      for (let i=0; i<a.length && !exists; i++){
          exists = a[i].name === user.name ;
      }
       if(exists===true)
       {
       c.push(Object.assign({},user,{exists}));
       return;
       }
     
    });

    console.log(c);
Linda Paiste
  • 38,446
  • 6
  • 64
  • 102
Rahul Kumar
  • 65
  • 3
  • 11
  • How, schematically in your own words, would you solve it at first? And then, where do you need support? – Peter Seliger Mar 29 '21 at 19:47
  • 1
    Second question(s); do you need a generic solution for the item's equality check? Which means, does one have to deal with complex/nested object structures or not? In case of just one level of key-value pairs, as shown with the example code, does one just deal with a key and its string value (also exactly like the example shows)? – Peter Seliger Mar 29 '21 at 19:56
  • `const res = array2.find(o2 => array1.some(o1 => o1.name === o2.name && o1.lastname === o2.lastname));` I'm not sure if I should write an answer or if this can be flagged as a duplicate. – Linda Paiste Mar 29 '21 at 19:57

2 Answers2

4

Solution

const res = array2.find((o2) =>
  array1.some((o1) => o1.name === o2.name && o1.lastname === o2.lastname)
);

Explanation

You don't need to use "classic" let i=0 loop techniques because you can make use of the methods Array.prototype.some() and Array.prototype.find().

We want the first element of array2 that matches a condition, so we use array2.find(), which stops as soon as any element returns true for the provided callback.


The condition we are checking for the elements of array2 is that they are contained in array1. If these were primitive values then you could use Array.prototype.includes(). More explanation of that can be found in the answers to these questions:

When dealing with objects, we can't rely on a strict === comparison between the two objects. That would be true if and only if the two objects are references to the same object in memory. But we want to determine that an object is "the same" if all of its properties have the same values. You could use a helper like lodash's isEqual or check out the answers to this question:

Here we only have two properties which are both string so it is easy to define our own comparison check. We say that o1 and o2 match if:

o1.name === o2.name && o1.lastname === o2.lastname

We want to find() in array2 the first element where array1 contains a match. We use array1.some() to check for matches. This function returns true if any element of array1 matches the condition. It will stop as soon as it finds any true element.

const res = array2.find((o2) =>
  array1.some((o1) => o1.name === o2.name && o1.lastname === o2.lastname)
);

By defining all callbacks inline we avoid the need for any Typescript types annotations. The types of o1 and o2 can be inferred properly from the types of array1 and array2. You could break this into pieces, but you would need to write out the types for the arguments of your functions.

Typescript Playground Link

Linda Paiste
  • 38,446
  • 6
  • 64
  • 102
0

You are nearly there: you only need to restrict the output to the first match

It took a while to understand your question. If I understand rightly, you have 2 arrays, a containing objects, and b containing objects that may or may not match objects in a.

You want to construct an array c containing only the first matching object between the two arrays.

It is not clear to me what you mean by "first match". For example:

From [p, q, r, s, r] and [m, n, p, s, r, s], the first match could be:

  • [r] if you mean "the first in the first array and then stop"
  • [s] if you mean "the first in the second array and then stop"
  • [r, s] if you mean "for each item in the first array, the first match in the second"
  • [s, r] if you mean vice versa

Your examples are, unfortunately, not helpful in diagnosing which of the 4 options you mean, since there is only one match.

Another thing that is not clear is whether you need only the .name property to match (which is what your question, and the code snippet, suggest), or whether you want all properties to match.

Modification of your code

I have modified your code retaining your original structure of forEach, as you will find it familiar. I like your exists variable. It would work, if we use it to prevent further matches being detected.

This code finds only one match overall, and takes the first item in the first array that matches any item in the second array (the first option in my 4 options above).

const a = [{name:'Ram',lastname:'kumar'},{name:'Shyam',lastname:'kumar'},{name:'Mohan',lastname:'kumar'},{name:'Amit',lastname:'kumar'}];
const b = [{name:'Anil',lastname:'kumar'},{name:'Shyam',lastname:'kumar'},{name:'Mohan',lastname:'kumar'},{name:'Anjali',lastname:'kumari'}];
const c = [];

let exists = false

b.forEach(userB => {
  a.forEach(userA => {
      if ((userA.name === userB.name) && !exists){
        c.push(userB)
        exists = true
      }
  })     
});

console.log(c);

Other meanings

If you require both .name and .lastname to match, adjust the if accordingly.

ProfDFrancis
  • 8,816
  • 1
  • 17
  • 26