Nilesh
Nilesh

Reputation: 628

How to group two arrays using key in node js

I have below two objects which I want to merge.

[
    {
        "response_code": 1,
        "response_message": [{
            "a": 1000,
            "b": 1000001,
            "c": 10000002
        }]
    }]
[
    {
        "response_code": 1,
        "response_message": [{
            "a": 2000,
            "b": 2000001,
            "c": 20000002
        }]
    }
]

I want to merge them like below by having only one value of response code and merge values of response message like below way.

{
    "response_code": 1,
    "response_message": [
    {
        "a": 1000,
        "b": 1000001,
        "c": 10000002
    },
    {
        "a": 2000,
        "b": 2000001,
        "c": 20000002
    }]
}

Really stuck with such complicated merging where I want only once the value of response code and merge the values of response message.

Here I want to remove response code value from other array and merge/group the response message value with fist array.

Upvotes: 0

Views: 399

Answers (4)

Nilesh
Nilesh

Reputation: 628

I have resolved the array merging by below code.

      const mergedArray = [];
      myarray.forEach((obj, index) => {
        var newObj = {}
        if(index > 0){
          if(mergedArray.length > 0){
            for(let i=0; i<obj.response_message.length;i++){
              mergedArray[0].response_message.push(obj.response_message[i]);
            }
          }
        }else{
          newObj["response_code"] = obj.response_code ;
          newObj["response_message"] =  obj.response_message;
          mergedArray.push(newObj);
             }
      })

Upvotes: 0

Anuj Pancholi
Anuj Pancholi

Reputation: 1213

I whipped up a little function for you:

And in accordance with the concerns raised by you in the comments, along with the test case where response_message was a string, I have edited the code snippet to include multiple cases to test.

const inputs = [
    [{
            "response_code": 1,
            "response_message": [{
                "a": 1000,
                "b": 1000001,
                "c": 10000002
            }]
        },

        {
            "response_code": 1,
            "response_message": [{
                "p": 1000,
                "q": 1000001,
                "r": 10000002
            }]
        }
    ],
    [{
            "response_code": 1,
            "response_message": [{
                "a": 1000,
                "b": 1000001,
                "c": 10000002
            }]
        },
        {
            "response_code": 1,
            "response_message": 'No data'
        }
    ],
    [{
            "response_code": 1,
            "response_message": 'No data'
        },
        {
            "response_code": 1,
            "response_message": 'No data'
        }
    ]

]

const getGroupedArr = (arr) => {
    const codeMap = arr.reduce((cMap,obj) => {
        let existingMessageArr = cMap.get(obj.response_code);
        let arrayToAdd = Array.isArray(obj.response_message) ? obj.response_message : [];
        if(existingMessageArr){
            existingMessageArr.push(...arrayToAdd);
        } else {
            cMap.set(obj.response_code,arrayToAdd);
        }
        return cMap;
    },new Map());
    const iterator = codeMap[Symbol.iterator]();
    const resultArr = [];
    for (let item of iterator) {
        resultArr.push({
            response_code: item[0],
            response_message: item[1]
        })
    }
    return resultArr;
}

inputs.forEach((inputArr,index) => {
    console.log(`Result for input ${index+1}`,getGroupedArr(inputArr));
})

Notice that I used Map where in JS most people prefer objects because maps in JS are iterable, but with an object I would've had to do an extra Object.keys() step, so this makes is slightly more efficient than the object approach, though a little more verbose.

Also note that in the third case, when no object with a particular response_code has any data, the result would be an empty array rather than a string. In weakly typed environments like JS, it is always a good practice to maintain some type consistency (which actually makes the input value of 'No data' in response_code not ideal), otherwise you may need to put type checks everywhere (like in the edited funciton in the above snippet).

Same function can be used in a contraint you mentioned in the comments, when the objects with same response_code exist in two different arrays (the two input arrays can simply be merged into one):

const inputArr1 = [{
            "response_code": 1,
            "response_message": [{
                "a": 1000,
                "b": 1000001,
                "c": 10000002
            }]
        }]

const inputArr2 = [{
            "response_code": 1,
            "response_message": [{
                "p": 1000,
                "q": 1000001,
                "r": 10000002
            }]
        }]

const getGroupedArr = (arr) => {
    const codeMap = arr.reduce((cMap,obj) => {
        let existingMessageArr = cMap.get(obj.response_code);
        let arrayToAdd = Array.isArray(obj.response_message) ? obj.response_message : [];
        if(existingMessageArr){
            existingMessageArr.push(...arrayToAdd);
        } else {
            cMap.set(obj.response_code,arrayToAdd);
        }
        return cMap;
    },new Map());
    const iterator = codeMap[Symbol.iterator]();
    const resultArr = [];
    for (let item of iterator) {
        resultArr.push({
            response_code: item[0],
            response_message: item[1]
        })
    }
    return resultArr;
}


console.log(getGroupedArr([...inputArr1,...inputArr2]));

Upvotes: 1

Eggon
Eggon

Reputation: 2386

    const arrayOf0 = yourArray.filter(item => item.response_code===0)
    const arrayOf1 = yourArray.filter(item => item.response_code===1)
    const merged0 = {response_code: 0, response_message: []};
    const merged1 = {response_code: 1, response_message: []};
    arrayOf0.forEach(item => { 
merged0.response_message.push(item.response_message[0]
}) 
    arrayOf1.forEach(item => {
 merged1.response_message.push(item.response_message[0]
})

Something like this?

Upvotes: 0

JulioSa
JulioSa

Reputation: 128

I think you're looking for a groupby.

Check this good old post from stackoverflow and be aware of the different answers/ implementaions: Most efficient method to groupby on an array of objects

Upvotes: 0

Related Questions