简体   繁体   中英

How to use reduce method within an array to convert multiple Json objects with common key into a single Json object?

I have a function within NodeJS which is returning Json Javascript object.

let rows = function1();

Here rows look like:

"rows": [
    {
    "Hostname": "abc123",
    "name": "name1",
    "Status": "PASS",
    "Heading": "Not Applicable"
    },
    {
    "Hostname": "abc123",
    "name": "name2",
    "Status": "FAIL",
    "Heading": "Not Applicable"
    },
    {
    "Hostname": "abc235",
    "name": "name1",
    "Status": "FAIL",
    "Heading": "Not Applicable"
    },
    {
    "Hostname": "abc235",
    "name": "name2",
    "Status": "FAIL",
    "Heading": "Not Applicable"
    }
]

Here, rows can have any number of Json objects for the same Hostname key:

"rows": [
    {
    "Hostname": "abc123",
    "name": "name1",
    "Status": "PASS",
    "Heading": "Not Applicable"
    },
    {
    "Hostname": "abc123",
    "name": "name2",
    "Status": "FAIL",
    "Heading": "Not Applicable"
    },
    {
    "Hostname": "abc123",
    "name": "name3",
    "Status": "FAIL",
    "Heading": "Not Applicable"
    },
 ...
    {
    "Hostname": "abc235",
    "name": "name1",
    "Status": "FAIL",
    "Heading": "Not Applicable"
    },
    {
    "Hostname": "abc235",
    "name": "name2",
    "Status": "FAIL",
    "Heading": "Not Applicable"
    },
    {
    "Hostname": "abc235",
    "name": "name3",
    "Status": "FAIL",
    "Heading": "Not Applicable"
    }
...
]

I want to modify the rows array such that all Javascript objects belonging to one Hostname are converted into a single Json object:

"rows": [
    {
    "Hostname": "abc123",
    "name1Status": "PASS",
    "name1Heading": "Not Applicable"
    "name2Status": "FAIL",
    "name2Heading": "Not Applicable"
    "name3Status": "FAIL",
    "name3Heading": "Not Applicable"
    ...
    },
    {
    "Hostname": "abc235",
    "name1Status": "FAIL",
    "name1Heading": "Not Applicable"
    "name2Status": "FAIL",
    "name2Heading": "Not Applicable"
    "name3Status": "FAIL",
    "name3Heading": "Not Applicable"
    ...
    }
]

I have written the following code but it overwrites all key value pairs and shows Json objects related to the last Hostname only

const res = rows.reduce((acc, rec) => {
    let result = { ...acc, [`Hostname`]: rec.Hostname,  [`${rec.name}Status`]: rec.Status, [`${rec.name}Heading`]: rec.Heading  }
    return result
}, [])

{
    "Hostname": "abc235",
    "name1Status": "FAIL",
    "name1Heading": "Not Applicable"
    "name2Status": "FAIL",
    "name2Heading": "Not Applicable"
    "name3Status": "FAIL",
    "name3Heading": "Not Applicable"
}

There could be some form of for loop outside of res so that it takes into account all distinct Hostname keys

JSON elements ?

Anyway: this reducer should do it (using a helper method).

 const createEntry = (obj, value) => ({...obj, [`${value.name}Status`]: value.Status, [`${value.name}Heading`]: value.Heading}); console.log(getRows().reduce( (acc, value) => ( {...acc, [value.Hostname]: createEntry(acc[value.Hostname], value)} ), {}) ); function getRows() { return [ { "Hostname": "abc123", "name": "name1", "Status": "PASS", "Heading": "Not Applicable" }, { "Hostname": "abc123", "name": "name2", "Status": "FAIL", "Heading": "Not Applicable" }, { "Hostname": "abc123", "name": "name3", "Status": "FAIL", "Heading": "Not Applicable" }, { "Hostname": "abc235", "name": "name1", "Status": "FAIL", "Heading": "Not Applicable" }, { "Hostname": "abc235", "name": "name2", "Status": "FAIL", "Heading": "Not Applicable" }, { "Hostname": "abc235", "name": "name3", "Status": "FAIL", "Heading": "Not Applicable" } ]; }
 .as-console-wrapper { top: 0; max-height: 100%;important; }

You could take an object for grouping and return the grouped values.

 var data = [{ Hostname: "abc123", name: "name1", Status: "PASS", Heading: "Not Applicable" }, { Hostname: "abc123", name: "name2", Status: "FAIL", Heading: "Not Applicable" }, { Hostname: "abc235", name: "name1", Status: "FAIL", Heading: "Not Applicable" }, { Hostname: "abc235", name: "name2", Status: "FAIL", Heading: "Not Applicable" }], keys = ["Status", "Heading"], result = Object.values(data.reduce((r, { Hostname, name, ...o }) => { r[Hostname] = r[Hostname] || { Hostname }; keys.forEach(k => r[Hostname][name + k] = o[k]); return r; }, {})); console.log(result);
 .as-console-wrapper { max-height: 100%;important: top; 0; }

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