mapping two arrays of equivalent length by object attributes javascript

59 Views Asked by At

I have two arrays:

Array 1:

[
    {
        name: 'Bob',
        traits: {
            id: 1
        }
    }, {
        name: 'Karl',
        traits: {
            id: 2
        }
    }, {
        name: 'Joseph',
        traits: {
            id: 3
        }
    }
]

Array 2:

[
    {
        name: 'Karl',
        user_id: 2,
        dog: 'Rottweiler'
    }, {
        name: 'Joseph',
        user_id: 3,
        dog: 'Poodle'
    }, {
        name: 'Bob',
        user_id: 1,
        dog: 'Puppy'
    }
]

Desired outcome:

I want to be able to merge the second array into the first array by finding what element user_id matches with id and then adding the object to array.

For example:

array 1 obj

{
    name: 'Bob',
    traits: {
        id: 1
    }
}

Since the id matches with array 2 obj user_id:

{
    name: 'Bob',
    user_id: 1,
    dog: 'Puppy'
}

Final outcome will be:

{
    name: 'Bob',
    traits: {
        name: 'Bob',
        user_id: 1,
        dog: 'Puppy'
    }
}
4

There are 4 best solutions below

0
trincot On

Turn the second array into a map keyed by user_id, and then iterate the first array. Find the corresponding object in the map, and spread the matching object value into the traits property:

let arr1 = [{name: 'Bob',traits: {id: 1}},{name: 'Karl',traits: {id: 2}},{name: 'Joseph',traits: {id: 3}}];
let arr2 = [{name: 'Karl', user_id: 2,dog: 'Rottweiler'},{name: 'Joseph', user_id: 3,dog: 'Poodle'},{name: 'Bob',user_id: 1,dog: 'Puppy'}];

let map = new Map(arr2.map(item => [item.user_id, item]));

let result = arr1.map(item => {
    let traits = map.get(item.traits.id);
    return traits ? { ...item, traits} : item;
});

console.log(result);

As lookup in a map has an amortised time complexity of O(1), this is more efficient than finding the key in the array on every iteration (like with calling find).

0
DecPK On

You can easily achieve this result using map and find. Just map over the first array and find the element with obj.traits.id in the arr2. then return the desired result.

const arr1 = [
  {
    name: "Bob",
    traits: {
      id: 1,
    },
  },
  {
    name: "Karl",
    traits: {
      id: 2,
    },
  },
  {
    name: "Joseph",
    traits: {
      id: 3,
    },
  },
];

const arr2 = [
  {
    name: "Karl",
    user_id: 2,
    dog: "Rottweiler",
  },
  {
    name: "Joseph",
    user_id: 3,
    dog: "Poodle",
  },
  {
    name: "Bob",
    user_id: 1,
    dog: "Puppy",
  },
];

const result = arr1.map((obj) => {
  const { name, traits } = obj;
  const isExist = arr2.find((o) => o.user_id === traits.id);
  if (isExist) {
    return { name, traits: { ...isExist } };
  }
  return obj;
});

console.log(result);

0
Dor Ben Itzhak On

arr2.forEach((obj) => {
    const idx = arr1.findIndex((o) => o.traits.id === obj.user_id);
    if (idx !== -1) {
        arr1[idx] = { ...arr1[idx], traits: { ...obj } }
    }
})

console.log(arr1[0]) // { name: 'Bob', traits: { name: 'Bob', user_id: 1, dog: 'Puppy' } }

0
prashanth Sasidharan On

let a = [
    {
        name: 'Bob',
        traits: {
            id: 1
        }
    }, {
        name: 'Karl',
        traits: {
            id: 2
        }
    }, {
        name: 'Joseph',
        traits: {
            id: 3
        }
    }
    ];

    let b = [
        {
            name: 'Karl',
            user_id: 2,
            dog: 'Rottweiler'
        }, {
            name: 'Joseph',
            user_id: 3,
            dog: 'Poodle'
        }, {
            name: 'Bob',
            user_id: 1,
            dog: 'Puppy'
        }
    ];
    
    a.map(aobj =>{
    let sameIdObj = b.find( bobj => bobj.user_id === aobj.traits.id )
    sameIdObj && (aobj.traits =  sameIdObj)
    })

    console.log(a);