skip to Main Content

I have two arrays of objects, the objects within these arrays have a slightly different keys but share same id.

What i am trying to do is merge these two arrays into one that contains all the elements from both without duplicates.

array one:

[
   {id: 'ABC_123', value: 10, label: 'tree', level: 'mid'},
   {id: 'ABC_456', value: 11, label: 'grass', level: 'top'}
];

array two:

[
   {levelId: 'ABC_123', value: 10, label: 'tree', level: 'mid'},
   {levelId: 'ABC_456', value: 11, label: 'grass', level: 'top'},
   {levelId: 'ABC_789', value: 11, label: 'bush', level: 'low'}
];

I want to bring all the new elements from array two into array one in this example i want element with levelId: 'ABC_789 to move into array one and change the levelId key into id:

result:

[
       {id: 'ABC_123', value: 10, label: 'tree', level: 'mid'},
       {id: 'ABC_456', value: 11, label: 'grass', level: 'top'}
       {id: 'ABC_789', value: 11, label: 'bush', level: 'low'}

]

I have tried mapping over them matching the id’s and creating new array but I cant get the desired result

4

Answers


  1. You could collect the id values from the first array, but them in a set, and iterate the second collection to select those that have no match in that set. With destructuring assignment you can achieve the change of levelId to id:

    // Your example input:
    const a = [{id: 'ABC_123', value: 10, label: 'tree', level: 'mid'},{id: 'ABC_456', value: 11, label: 'grass', level: 'top'}];
    const b = [{levelId: 'ABC_123', value: 10, label: 'tree', level: 'mid'},{levelId: 'ABC_456', value: 11, label: 'grass', level: 'top'},{levelId: 'ABC_789', value: 11, label: 'bush', level: 'low'}];
    
    // Get the id values from the first array
    const keys = new Set(a.map(({id}) => id));
    // Select the items from the second array, and if their levelId is not in 
    //    the set, add them to the first array:
    for (const {levelId: id, ...rest} of b) {
        if (!keys.has(id)) a.push({id, ...rest});
    }
    
    console.log(a);
    Login or Signup to reply.
  2. You need to loop over both structures.

    I am using reduce as a loop structure and find acts as one too.

    You essentially want to look through the possible new values and determine if it exists already in the first array. If it doesn’t exist then push its value into array 1.. in this case a new object structure.

    Here is a rough solution:

    let arr1 = [
       {id: 'ABC_123', value: 10, label: 'tree', level: 'mid'},
       {id: 'ABC_456', value: 11, label: 'grass', level: 'top'}
    ];
    
    let arr2 = [
       {levelId: 'ABC_123', value: 10, label: 'tree', level: 'mid'},
       {levelId: 'ABC_456', value: 11, label: 'grass', level: 'top'},
       {levelId: 'ABC_789', value: 11, label: 'bush', level: 'low'}
    ];
    
    
    function mergeArr(a1, a2) {
        return a2.reduce((newArr, el) => {
          const has = a1.find((entry) => entry.id === el.levelId);
    
          if (!has) {
            newArr.push({
              id: el.levelId,
              value: el.value,
              label: el.label,
              level: el.level
            });
          }
    
          return newArr;
        }, a1)
    }
    
    console.log(mergeArr(arr1, arr2));
    
    Login or Signup to reply.
  3. I would just initiate the result with arr1, then for each element in arr2 check if already exist. If yes – ignore it, otherwise append to the result and change levelId to id:

    const arr1 = [
       {id: 'ABC_123', value: 10, label: 'tree', level: 'mid'},
       {id: 'ABC_456', value: 11, label: 'grass', level: 'top'}
    ];
    
    const arr2 = [
       {levelId: 'ABC_123', value: 10, label: 'tree', level: 'mid'},
       {levelId: 'ABC_456', value: 11, label: 'grass', level: 'top'},
       {levelId: 'ABC_789', value: 11, label: 'bush', level: 'low'}
    ];
    
    const merge = (arr1, arr2) => {
        const cachedIds = arr1.reduce((acc, value) => {
            return {
                ...acc,
                [value.id]: true
            };
        }, {});
    
        return arr2.reduce((acc, value) => {
            if (cachedIds[value.levelId]) {
                return acc;
            }
    
            const transformedObject = {
                id: value.levelId,
                ...value,
            }
    
            delete transformedObject.levelId;
    
            return [
                ...acc,
                transformedObject,
            ];
        }, arr1);
    }
    
    console.log(merge(arr1, arr2))

    Assuming the length of the array1 is n and length of arr2 is m, this solution complexity is:

    Run time: O(m)
    Space: O(n)

    Login or Signup to reply.
  4. You can use the map function that is part of the array in JS.

    const array1 = [
       {id: 'ABC_123', value: 10, label: 'tree', level: 'mid'},
       {id: 'ABC_456', value: 11, label: 'grass', level: 'top'}
    ]
    const array2 = [
       {levelId: 'ABC_123', value: 10, label: 'tree', level: 'mid'},
       {levelId: 'ABC_456', value: 11, label: 'grass', level: 'top'},
       {levelId: 'ABC_789', value: 11, label: 'bush', level: 'low'}
    ];
    const result = array2.map(item2 => {
    //destructure the array to separate out the level id and the rest of the params //you want
      const { levelId, ...neededParams} = item2;
    //return with object with levelId mapped to ID
      return {
        id: levelId,
        ...neededParams
      };
    });
    
    //concat the array to have all values in the one array with the first //arrays structure
    const finalArray = [...array1, ...result];
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search