0

let obj1 = [{field1:11, field2:12, field3:13}, {field1:21, field2:22, field3:23}, {field1:31, field2:32, field3:33}, {field1:41, field2:42, field3:43}];
let obj2 = [{attribute1:21, attribute2:22}, {attribute1:31, attribute2:32}, {attribute1:11, attribute2:12}];
    
let output = [];
    
obj1.map(o1 => {
  for (let i=0;i<obj2.length;i++) {
    if (o1.field1 === obj2[i].attribute1) {
      output.push(Object.assign(obj2[i], o1));
      obj2.splice(i,1);
      break;
    }   
  }
});
console.log(output); //*[{attribute1:11,attribute2:12,field1:11,field2:12,field3:13},{attribute1:21,attribute2:22,field1:21,field2:22,field3:23},{attribute1:31,attribute2:32,field1:31,field2:32,field3:33}]*

The above code compares two different objects with its fields. Here I am using 2 loops. So my question is, do we have any better approach to achieve the same? Without two loops or using any package or the best way

Tyler2P
  • 2,324
  • 26
  • 22
  • 31

1 Answers1

0

You can use find to find the first element where the statement is true instead of looping and manually checking if the statement is true or false. Sadly find is also an iterative method but I don't see any other way to improve this. I am using filter to remove the elements that don't fulfil the condition o2.attribute1 === o1.field1.

let obj1 = [{field1:11, field2:12, field3:13}, {field1:21, field2:22, field3:23}, {field1:31, field2:32, field3:33}, {field1:41, field2:42, field3:43}];
let obj2 = [{attribute1:21, attribute2:22}, {attribute1:31, attribute2:32}, {attribute1:11, attribute2:12}];

const output = obj1.map(o1 => {
    let obj2Value = obj2.find(o2 => o2.attribute1 === o1.field1);
    return obj2Value ? Object.assign(obj2Value, o1) : null;
}).filter(o => o !== null);

console.log(output);

Alternatively you can use forEach to do this:

let obj1 = [{field1:11, field2:12, field3:13}, {field1:21, field2:22, field3:23}, {field1:31, field2:32, field3:33}, {field1:41, field2:42, field3:43}];
let obj2 = [{attribute1:21, attribute2:22}, {attribute1:31, attribute2:32}, {attribute1:11, attribute2:12}];

let output = [];
obj1.forEach(o1 => {
    let obj2Value = obj2.find(o2 => o2.attribute1 === o1.field1);
    obj2Value ? output.push(Object.assign(obj2Value, o1)) : '';
});

console.log(output);

There are several approaches to achieve this. Also remember map already returns a new array so no need to use push inside, just return. Check this for better understanding: https://stackoverflow.com/questions/34426458/javascript-difference-between-foreach-and-map#:~:text=forEach%20%E2%80%9Cexecutes%20a%20provided%20function,every%20element%20in%20this%20array.%E2%80%9D .

Juljo Shahini
  • 138
  • 10
  • https://stackoverflow.com/questions/50843682/for-loop-with-break-vs-find-in-javascript#:~:text=The%20one%20big%20difference%20that,a%20variable%20to%20use%20later Here you can find performance comparisons and more. – Juljo Shahini Jan 13 '23 at 10:19
  • Hey, thanks for your input. So, that means we don't have any other way and we need to have 2 loops (or iteratives) nested? And find is faster than other iteratives. – Vishal Gupta Jan 13 '23 at 14:45
  • @VishalGupta I don't think you can, unless somebody comes up with something really creative. This should be the best option for you in my opinion (unless somebody comes up with a better answer), the code is cleaner and should be a bit faster according to the sources mentioned. – Juljo Shahini Jan 13 '23 at 15:47