Modify an array by incorporating values from another array that have a matching property

I have two arrays that look 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'
    }]

My goal is to update the values in array 1 with the corresponding object values from array 2, based on matching id values. The expected result should be:

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

I tried the following code but it's not functioning correctly.

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

If you have any suggestions on how to achieve this, please advise. Thank you.

Answer №1

Take a look at this concise one-liner:

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

Explanation: The code is mapping over array1 and searching for the matching id in array2. If a match is found (

array2.find(a => a.id == e.id)?.name
), it updates the name property to the found value, otherwise it retains the original name.

Here's a 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 based on @Roster's suggestion, if you want to update the entire entry use this line:

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

For another 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);

Answer №2

Transform the update array into a Map, then loop through the target array using Array.map(), and combine it with the object of the corresponding key in the updateMap if it is present:

const mergeArrays = (keySelector, targetArray, updateArray) => {
  const updateMap = new Map(updateArray.map(item => [keySelector(item), item]))
  
  return targetArray.map(item => {
    const key = keySelector(item)
    
    return updateMap.has(key)
      ? { ...item, ...updateMap.get(key)}
      : item
  })
}

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

const mergedResult = mergeArrays(o => o.id, initialArray, newArray);
console.log(mergedResult);

With TypeScript support (TS playground):

const mergeArrays = <T>(keySelector: (arg: T) => any, targetArray: T[], updateArray: T[]) => {
  const updateMap = new Map(updateArray.map(item => [keySelector(item), item]))
  
  return targetArray.map(item => {
    const key = keySelector(item)
    
    return updateMap.has(key)
      ? { ...item, ...updateMap.get(key)}
      : item
  })
}

Answer №3

Implementing a hashmap to efficiently update an array.

The primary purpose of utilizing a hashmap in this scenario is to enhance performance.

const originalArray = [
    { id: 1, name: "Alpha" },
    { id: 2, name: "Beta" },
    { id: 3, name: "Gamma" },
];

const updatedArray = [
    { id: 1, name: "X" },
    { id: 2, name: "Y" },
];

const hashMap = updatedArray.reduce((accumulator, item) => {
    const { id } = item;
    if (!accumulator[id]) {
        accumulator[id] = item;
    }
    return accumulator;
}, {});

const finalOutput = originalArray.map(item => {
    const newName = hashMap[item.id]?.name;
    if (newName) {
        item.name = newName;
    }
    return item;
});

console.log(finalOutput);

Answer №4

Below is an approach utilizing 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 function loops through the items in array2 and verifies their presence within array1 based on the specified identifier.

Depending on whether the item exists in array1 or not, it will either be updated with information from array2, or the item from array2 is added to array1.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for displaying a close icon after completing a file upload

I need to implement a feature where once a user uploads a file, a cross sign should be enabled on the file. I attempted to use javascript for this functionality, but it seems to not be working as expected. There are more than 8-10 different file types that ...

Is there a way to prevent QtLinguist from opening every time Visual Studio tries to display a TypeScript file?

Ever since I installed Qt tools for Visual Studio, my Ctrl+click on a class name triggers Qt Linguist: https://i.stack.imgur.com/USAH1.png This hinders me from checking type definitions, even though Visual Studio has already parsed them. The type informa ...

Await keyword cannot be used due to undefined object reference

Currently in the process of implementing authentication into my node API. Using PassportJS, although I am fairly new to this so please bear with me. The goal is to add a local strategy and verify the user's password during login: // Local Strategy ...

Instantly magnifying on the initial point regardless of the zoom type chosen is a feature of Chart.js zoom

Despite adding zoom functionality to my line chart, I am facing an issue where it automatically zooms in to the first point and does not allow me to zoom back out, except for using the reset zoom function. The zoom out function is also not working properly ...

Unexpectedly, the NodeJS application experiences a crash following numerous requests

I can't seem to figure out why my Nodejs app crashes after a certain number of requests (currently 22). The issue arises with this simple get request handler: router.get('/api/docs/fetch', async (req,res) => { try{ let docs = ...

What is the best way to transfer data from a parent component to a child component in ReactJs?

When dealing with nested react elements, how can you pass values from the parent element to a child element that is not directly inside the parent element? React.render( <MainLayout> <IndexDashboard /> </MainLayout>, document.b ...

Navigating with Reach Router only updates the URL, not the component being rendered

Is there a way to programmatically navigate using Reach Router in React? I have noticed that when updating the URL, the route does not render. Even though the URL changes, the original component remains displayed according to the React developer tools. Ho ...

"Enhance Your Highchart Experience by Adding Hyperlinks to Every Segment of Your Stacked Bar

I am seeking to assign a specific link to each segment of a stacked 100% bar chart. Check out this demo of a stacked bar chart: Here's what I am trying to accomplish: Please visit , input data in the left table, and submit it. After submission, you ...

"JQuery's selector is failing to locate elements once they have been loaded through an

I am facing an issue where jQuery selectors are not working on elements loaded from the server via Ajax requests, but they work fine in normal mode. $('#myid').change(function(){ alert('OK!'); }); <select id="myid"> <optio ...

Navigating to a precise location on a webpage with React.js

I want to implement a straightforward action where the page automatically scrolls to a specific position upon loading. However, my attempts to execute this action have been unsuccessful so far. Is there an alternative method to achieve this in a React ap ...

Example of Next.js Authentication - redirecting according to authentication status, encapsulating within other functionalities

I'm currently working on a project using next.js with authentication. The authentication is set up and working, but I'm having trouble displaying the data in my navbar. Originally, I was using firebase for authentication, but now I have it set u ...

output the elements of a list of strings

I am trying to generate a list of strings based on a given list of numbers. For example, let's say the input list is list=[1,2,5,25,6] Expected output: ['Odd', 'Even', 'Odd, multiples of 5 and odd', 'multiples o ...

Executing a callback function in AngularJS after dynamically rendering elements with `ng-repeat`

Many posts demonstrate how to implement callback functions in directives to wait for ng-repeat to finish before calling a function. Here is an example: <div ng-repeat="Object in Objects" class="objectClass" on-finish-render>{{Object.Overlay}</div ...

Pause and check for the completion of data loading in mapstate

I have a stored userProfile in the Vuex state in order to access it throughout my project. However, when I try to use it in the created() hook, the profile is not loaded yet during the initial page load. Although the object exists, it does not contain any ...

Utilize the precise Kendo chart library files rather than relying on the kendo.all.min.js file

My application currently uses the Kendo chart, and for this purpose, it utilizes the "kendo.all.min.js" file which is quite large at 2.5 MB. To optimize the speed performance of the application, I decided to only include specific Kendo chart libraries. In ...

The second node child process encounters execution issues in Linux

For a challenge, I needed to find a way to automatically restart my bot within itself. After some trial and error, I came up with a solution. However, when testing on a Raspberry Pi via ssh, the process exits after the first child process ends. Surprisingl ...

Regular expression pattern for consistently capitalizing the phrases "CA" and "USA" in an address string

end_address = 'joe's home, 123 test avenue, los angeles, ca, usa 90210'; end_address = end_address.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}); The outcome of this code will ...

Unusual occurrences within stacked MUI Popper components

Below is a sample Node component that uses a button element to anchor an MUI Popper: type Props = { children?: React.ReactNode; }; const Node = ({ children }: Props) => { const [anchor, setAnchor] = React.useState(null); return ( <div> ...

What is the process for setting up URL parameters in Express JS?

I am working on creating an URL that can accept a query after the "?" operator. The desired format for the URL is "/search?q=". I am wondering how I can achieve this in Express JS, and also how I can integrate the "&" operator into it. ...

Javascript Flickering Effect in HTML5

Currently, I am in the process of creating a simple game using javascript without jQuery. However, I am facing an issue with flickering on the canvas due to the clearing command. After researching solutions online, I came across suggestions for implementin ...