Home > OS >  Update an array using another array based on matched property value
Update an array using another array based on matched property value

Time:02-19

I have two arrays like this

 let array1 =   [{
      'id': 1,
      'name': 'A'
    }, {
      'id': 2,
      'name': 'B'
    }, {
      'id': 3,
      'name': 'C'
    }]

let array2 =   [{
      'id': 1,
      'name': 'x'
    }, {
      'id': 2,
      'name': 'y'
    }]

I want to update array 1 with the array 2 object values which are matching based on id values. Result would be something like this.

 [{
      'id': 1,
      'name': 'x'
    }, {
      'id': 2,
      'name': 'y'
    }, {
      'id': 3,
      'name': 'C'
    }]

I have written something like this but not working .

    array1.forEach(item1 => {
        const itemFromArr2 = array2.find(item2 => item2.id== item1.id);
        if (itemFromArr2) {
           item1= itemFromArr2;
        }
     }
  )

Please suggest me how to do this.

CodePudding user response:

You might want to check this one-liner out:

array1.map(e => (e.name = array2.find(a => a.id == e.id)?.name || e.name, e));

Explanation: We are mapping over array1 and searching for the matching id in array2, if it is found (array2.find(a => a.id == e.id)?.name), we override the name property (e.name = ...), otherwise we keep it as it is (... || e.name).

Small example:

let array1 = [{
  'id': 1,
  'name': 'A'
}, {
  'id': 2,
  'name': 'B'
}, {
  'id': 3,
  'name': 'C'
}]

let array2 = [{
  'id': 1,
  'name': 'x'
}, {
  'id': 2,
  'name': 'y'
}]

const newarray = array1.map(e => (e.name = array2.find(a => a.id == e.id)?.name || e.name, e));
console.log(newarray);

Edit according to @Roster's comment, if you want to override the whole entry use this line:

array1.map(e => (e = array2.find(a => a.id == e.id) || e, e));

Second example:

let array1 = [{
  'id': 1,
  'name': 'A'
}, {
  'id': 2,
  'name': 'B'
}, {
  'id': 3,
  'name': 'C'
}]

let array2 = [{
  'id': 1,
  'name': 'x'
}, {
  'id': 2,
  'name': 'y',
  'otherproperty': 42
}]

const newarray = array1.map(e => (e = array2.find(a => a.id == e.id) || e, e));
console.log(newarray);

CodePudding user response:

Using a hashmap to update the array.

The reason of hashmap is for performance.

const array1 = [
    { id: 1, name: "A" },
    { id: 2, name: "B" },
    { id: 3, name: "C" },
];

const array2 = [
    { id: 1, name: "x" },
    { id: 2, name: "y" },
];

const hashMap2 = array2.reduce((carry, item) => {
    const { id } = item;
    if (!carry[id]) {
        carry[id] = item;
    }
    return carry;
}, {});

const output = array1.map(item => {
    const newName = hashMap2[item.id]?.name;
    if (newName) {
        item.name = newName;
    }
    return item;
});

console.log(output);

CodePudding user response:

Here's a solution using Generics:

const array1 =   [{
      'id': 1,
      'name': 'A'
    }, {
      'id': 2,
      'name': 'B'
    }, {
      'id': 3,
      'name': 'C'
    }]

const array2 =   [{
      'id': 1,
      'name': 'x'
    }, {
      'id': 2,
      'name': 'y'
    }]


function mergeArray<T>(arr1: T[], arr2: T[], identifier: keyof T): T[] {
    for(const oItem of arr2){
        const itemInArr1 = 
            arr1.find(item => item[identifier] === oItem[identifier]);
        if(itemInArr1){
            for(const key in itemInArr1){
                itemInArr1[key] = oItem[key];
            }
        } else {
            arr1.push(oItem);
        }
    }
    return arr1;
}

console.log(mergeArray(array1,array2, 'id'));

Playground

This iterates over the itmes in array2and checks their existence inside array1 based on the identifier.

Based on whether or not the item exists in array1, the item will be modified, or the item from array2 is pushed into array1.

CodePudding user response:

Convert the update array to a Map, then iterate the target array with Array.map(), and merge it with the object of the same key in the upateMap if it exists:

const fn = (predicate, target, update) => {
  const updateMap = new Map(update.map(o => [predicate(o), o]))
  
  return target.map(o => {
    const key = predicate(o)
    
    return updateMap.has(key)
      ? { ...o, ...updateMap.get(key)}
      : o
  })
}

const array1 = [{"id":1,"name":"A"},{"id":2,"name":"B"},{"id":3,"name":"C"}]
const array2 = [{"id":1,"name":"x"},{"id":2,"name":"y"}]

const result = fn(o => o.id, array1, array2);
console.log(result);

With types (TS playground):

const fn = <T>(predicate: (arg: T) => any, target: T[], update: T[]) => {
  const updateMap = new Map(update.map(o => [predicate(o), o]))
  
  return target.map(o => {
    const key = predicate(o)
    
    return updateMap.has(key)
      ? { ...o, ...updateMap.get(key)}
      : o
  })
}
  • Related