Home > front end >  Merge two objects by a selector id
Merge two objects by a selector id

Time:11-07

I have two arrays A, B with objects from the database. I want to merge the objects from array B into array A that have a relation: (A[n].id == B[n].a_id).

const array_a = [
  {
    "id": 4,
    "status": 0,
  },
  {
    "id": 5,
    "status": 1,
  }
];

const array_b = [{
  active: 1,
  a_id: 5, // SELECTOR FOR MERGE
  created_at: '2022-11-05 20:29:29',
  firstname: 'user3',
  lastname: ''
}];

Expected result:

const result = [
  {
    "id": 4,
    "status": 0,
  },
  {
    "id": 5,
    "status": 1,
    "active": 1,
    "user_id": 5,
    "created_at": '2022-11-05 20:29:29',
    "firstname": 'user3',
    "lastname:" ''
}
];

I tried this approach from another SO answer and got nowhere.
https://stackoverflow.com/a/53462680/18066399 :-/

CodePudding user response:

First, make a dictionary to look up later as dict ={} where the key is a_id and the value is the whole object itself. then iterate through the second array and look for if there is something already in dict if it's then we need to get them by dict[val.id] and merge the values with the original object.

Learn about map() and reduce()

Trick:

As you said data come from a database so data can be bigger in size, So you may want to avoid loop nesting like inside .map() again another loop like filter find etc. Suppose your database returns 1000 items per each so if you use nested algorithms in the worst case you need to perform 1000*1000 = 1000000 steps which is slower :(

const array_a = [
  {
    "id": 4,
    "status": 0,
  },
  {
    "id": 5,
    "status": 1,
  }
];

const array_b = [{
  active: 1,
  a_id: 5, // SELECTOR FOR MERGE
  created_at: '2022-11-05 20:29:29',
  firstname: 'user3',
  lastname: ''
}];
      
      
  const dict = array_b.reduce((acc, val) => ({...acc, [val.a_id]: val}), {});
  const res = array_a.map(val=> {
    if(!dict[val.id]) return val; //If nothing in "dict" object by id we return original obj
    const mergedObj = {...val, ...dict[val.id]}; //Merge two objects
    delete Object.assign(mergedObj, {user_id: mergedObj.a_id})['a_id']; //create "user_id" by the value of "a_id"  and delete old key "a_id"
    return mergedObj;
  });
  console.log(res);

CodePudding user response:

const array_a = [
    {
      "id": 4,
      "status": 0,
    },
    {
      "id": 5,
      "status": 1,
    }
  ];
  
  const array_b = [{
    active: 1,
    a_id: 5, // SELECTOR FOR MERGE
    created_at: '2022-11-05 20:29:29',
    firstname: 'user3',
    lastname: ''
  }];


  const merged = array_a.map((item) => {
        const found = array_b.find((i) => i.a_id === item.id);
        return found ? { ...item, ...found } : item;
    });


console.log("merged",merged);

A simple way of doing it: while looping inside the array_a, we check if the id is available in array_b as a_id, and if it was, we merge the data.

CodePudding user response:

A simple way to do this would be to use map() and filter(). I don't know how big your result arrays from the database are. Of course, my way may not be the most efficient. But then neither would the others. Maybe you could already solve the problem with your database structure!

const array_a = [
  {
    "id": 4,
    "status": 0,
  },
  {
    "id": 5,
    "status": 1,
  }
];

const array_b = [{
  active: 1,
  a_id: 5, // SELECTOR FOR MERGE
  created_at: '2022-11-05 20:29:29',
  firstname: 'user3',
  lastname: ''
}];

const result = array_a.map(_a => {
  const n = array_b.filter(_b => _b._id == _a.id);
  return n.length ? {..._a, ...n[0]} : _a;
})

console.log(result)

Update with shorter solution

Inspired by this answer, which I personally found good. https://stackoverflow.com/a/61670621/18066399

const array_a = [
  {
    "id": 4,
    "status": 0,
  },
  {
    "id": 5,
    "status": 1,
  }
];

const array_b = [{
  active: 1,
  a_id: 5, // SELECTOR FOR MERGE
  created_at: '2022-11-05 20:29:29',
  firstname: 'user3',
  lastname: ''
}];

const result = array_a.map(_a => ({..._a, ...array_b.find(_b => _b.a_id === _a.id)}));

console.log(result)

  • Related