简体   繁体   中英

Javascript combine two array of objects

I would like to combine elements of 2 arrays based on the name. For example:

Array1 = [
  {name: "name1", language: "lang1"}, 
  {name: "name2", language: "lang2"}, 
  {name: "name3", language: "lang3"}]

Array2 = [
  {name: "name1", subject: "sub1"}, 
  {name: "name2", subject: "sub2"}, 
  {name: "name3", subject: "sub3"}]

I need to generate the following array:

Array3 = [
  {language: "lang1", subject: "sub1"}, 
  {language: "lang2", subject: "sub2"}, 
  {language: "lang3", subject: "sub3"}]

The logic I could think of was to write an explicit for loop to compare every element of first array with every element of second array and check if name matches as shown below.

let Array3 = []
for(let i=0;i<Array1.length;i++)
{
    let elem = Array1[i];
    for(let j=0;j<Array2.length;j++)
    {
        if(Array2[j].name===elem.name)
        {
            Array3.append({language: elem.language, subject: Array2[j].subject})
            break;
        }
    }
}

However, my actual dataset is quite large and this seems inefficient. How can this can be achieved in a more efficient manner (like using higher order functions or something)?

You need to iterate over the two arrays and group the generated object in a map having the name as the key :

 let Array1 = [ {name: "name1", language: "lang1"}, {name: "name2", language: "lang2"}, {name: "name3", language: "lang3"} ]; let Array2 = [ {name: "name1", subject: "sub1"}, {name: "name2", subject: "sub2"}, {name: "name3", subject: "sub3"} ]; let map = new Map(); Array1.forEach(e => map.set(e.name, {language: e.language})); Array2.forEach(e => { if(map.has(e.name)) map.set(e.name, {...map.get(e.name), subject: e.subject}); }); let Array3 = [...map.values()].filter(e => e.language && e.subject); console.log(Array3);

Using a Map for O(1) lookup of one of the arrays using name as key lets you iterate each array only once.

 const Array1=[{name:"name1",language:"lang1"},{name:"name2",language:"lang2"},{name:"name3",language:"lang3"}],Array2=[{name:"name1",subject:"sub1"},{name:"name2",subject:"sub2"},{name:"name3",subject:"sub3"}]; const a1Map = new Map(Array1.map(({name, ...r})=> [name, {...r}])); const res = Array2.map(({name, ...r}) => ({...r, ...a1Map.get(name)})) console.log(res)

Yes you are thinking in right order , you need to use the sort algorithm logics , I will say nested for loops will be just as good. With larger dataset , since you need to extract the values from two different array you can use the nested for loops.

 for(int i=0;i>array1.length();i++){
  This can be use for first array
  Define String x=",";
  For second
  for(int j=0;j>array2.length();j++)
  {
    Check if ( (","+j+",").contains(x)) then break;
    If array1 name found in array 2, store array3 as you want 
    Also Store value of j in x
    Like x=x +j+",";
   }}

This way your nested for loop will skip the comparison code. Above algo is raw but will reduce the complexity a significant bit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM