Search code examples
javascriptarraysnode-red

Javascript: Merge 2 arrays of objects into a new one, based on object properties


I have 2 arrays of JSON objects in javascript from which I would like to create a new array where I map on the property "Word_No" They look like this:

wordInfo (length 4000):

    [
    {
        "Word_No": "0",
        "Alarm_Bit": "0",
        "Alarm_No": "1",
        "Alarm_Description": "Alarm text 1"
    },
    {
        "Word_No": "0",
        "Alarm_Bit": "1",
        "Alarm_No": "2",
        "Alarm_Description": "Alarm text 2"
    },
    {
        "Word_No": "0",
        "Alarm_Bit": "2",
        "Alarm_No": "3",
        "Alarm_Description": "Alarm text 3"
    }
]

and wordTags (length 250):

    [
    {
        "Word_No": "0",
        "OPC_Tag": "HH.Application.TmpHmi_Var.TmpHmiC7.Alarm0_15"
    },
    {
        "Word_No": "1",
        "OPC_Tag": "HH.Application.TmpHmi_Var.TmpHmiC7.Alarm16_31"
    },
    {
        "Word_No": "2",
        "OPC_Tag": "HH.Application.TmpHmi_Var.TmpHmiC7.Alarm32_47"
    }
]

What I need to become is a new array: Alarmlist (length 4000):

    [
    {
        "OPC Tag": "HH.Application.TmpHmi_Var.TmpHmiC7.Alarm0_15",
        "Alarm_Bit": "0",
        "Alarm_No": "1",
        "Alarm_Description": "Alarm text 1"
    },
    {
        "OPC Tag": "HH.Application.TmpHmi_Var.TmpHmiC7.Alarm0_15",
        "Alarm_Bit": "1",
        "Alarm_No": "2",
        "Alarm_Description": "Alarm text 2"
    },
    {
        "OPC Tag": "HH.Application.TmpHmi_Var.TmpHmiC7.Alarm0_15",
        "Alarm_Bit": "2",
        "Alarm_No": "3",
        "Alarm_Description": "Alarm text 3"
    }
]

When I try to build this function using 2 for loops and mapping on the the Word_No property, it crashes.

    for (i = 0; i < wordInfo.length; ++i){  //Outer loop  
    for (j = 0; j < wordTags.length; ++j){  //Inner loop
        msg.Info_Word_No = wordInfo[i].Word_No //Woordnr
        msg.Tag_Word_No = wordTags[j].Word_No //Woordnr
        node.send(msg);
    } 
}

When I limit i and j to for example 10, the function executes and shows the word numbers in the debug window.

My idea was to map everything like this:

if(wordInfo[i].Word_No == wordTags[i].Word_No){
            var alarmTagInfo;
            alarmTagInfo.Alarm_No=wordInfo[i].Alarm_No;
            alarmTagInfo.OPC_Tag = wordTags[i].OPC_Tag;
            alarmTagInfo.Alarm_Bit = wordInfo[i].Alarm_Bit;
            msg.payload = alarmTagInfo;
            alarmlist.push(alarmTagInfo);
        }

But since the arrays are too big, the Node Red application just crashes. I'm not sure what would be the efficient way to handle this?


Solution

  • I'd suggest first creating a lookup object for OPC_Tag using Array.reduce() on wordTags - this will improve performance and avoid doing a .find() for each iteration of the loop on wordInfo.

    We'd then use Array.map() on wordInfo to create the final result:

    let wordInfo = [ { "Word_No": "0", "Alarm_Bit": "0", "Alarm_No": "1", "Alarm_Description": "Alarm text 1" }, { "Word_No": "0", "Alarm_Bit": "1", "Alarm_No": "2", "Alarm_Description": "Alarm text 2" }, { "Word_No": "0", "Alarm_Bit": "2", "Alarm_No": "3", "Alarm_Description": "Alarm text 3" } ]
    let wordTags = [ { "Word_No": "0", "OPC_Tag": "HH.Application.TmpHmi_Var.TmpHmiC7.Alarm0_15" }, { "Word_No": "1", "OPC_Tag": "HH.Application.TmpHmi_Var.TmpHmiC7.Alarm16_31" }, { "Word_No": "2", "OPC_Tag": "HH.Application.TmpHmi_Var.TmpHmiC7.Alarm32_47" } ] 
    
    // Create a lookup, mapping Word_No to OPC_Tag
    let wordTagsLookup = wordTags.reduce((acc, { Word_No, OPC_Tag }) => { 
        acc[Word_No] = OPC_Tag;
        return acc;
    }, {})
    
    let result = wordInfo.map(({ Word_No, Alarm_Bit, Alarm_No, Alarm_Description}) => { 
        return { Alarm_Bit, Alarm_No, Alarm_Description, OPC_Tag: wordTagsLookup[Word_No] };
    })
    
    console.log('Result:', result)
    .as-console-wrapper { max-height: 100% !important; }