JS Reduce and group JSON by deeply nested object

血红的双手。 提交于 2019-12-11 08:09:33

问题


I'm pulling via REST a JSON with an array of objects with some fields and some nested objects.

What I'm trying to create is a grouped summary object from the array of nested JSON objects with the following structure:

 var data = [
        {
            "Id": 79,
            "Date": "2019-02-17T00:00:00-07:00",
            "StartTime": 1535385600,
            "EndTime": 1535416200,
            "Slots": [
                {
                    "blnEmptySlot": false,
                    "strType": "B",
                    "intStart": 3600,
                    "intEnd": 5400,
                    "intUnixStart": 1535389200,
                    "intUnixEnd": 1535391000,
                }
            ],
            "OperationalUnit": 3,
            "Created": "2019-01-31T11:23:29+02:00",
            "StartTimeLocalized": "2019-02-17T10:00:00+02:00",
            "EndTimeLocalized": "2019-02-17T19:00:00+02:00",
            "_MetaData": {
                "AttendeeInfo": {
                    "Id": 111,
                    "AttendeeDisplayName": "att_name1",
                    "AttendeeProfile": 406,
                    "Attendee": 406,
                    "Photo": "avatar_path"
                  },
                "OperationalUnitInfo": {
                    "Id": 3,
                    "OperationalUnitName": "op_unit_name",
                    "Company": 1,
                    "CompanyName": "comp_name",
                    "LabelWithCompany": "comp_label"
                },
            }
        },
        {
            "Id": 80,
            "Date": "2019-02-17T00:00:00-07:00",
            "StartTime": 1535385600,
            "EndTime": 1535416200,
            "Slots": [
                {
                    "blnEmptySlot": false,
                    "strType": "B",
                    "intStart": 3600,
                    "intEnd": 5400,
                    "intUnixStart": 1535389200,
                    "intUnixEnd": 1535391000,
                }
            ],
            "OperationalUnit": 3,
            "Created": "2019-01-31T11:23:29+02:00",
            "StartTimeLocalized": "2019-02-17T10:00:00+02:00",
            "EndTimeLocalized": "2019-02-17T19:00:00+02:00",
            "_MetaData": {
                "AttendeeInfo": {
                    "Id": 112,
                    "AttendeeDisplayName": "att_name2",
                    "AttendeeProfile": 407,
                    "Attendee": 407,
                    "Photo": "avatar_path"
                  },
                "OperationalUnitInfo": {
                    "Id": 3,
                    "OperationalUnitName": "op_unit_name",
                    "Company": 1,
                    "CompanyName": "comp_name",
                    "LabelWithCompany": "comp_label"
                },
            }
        }
    ];

The overall purpose is to create a list of event objects with start and end DateTime, a LabelWithCompany String (deep nested object) and a list of all Attendees grouped by OperationalUnitName and Start and End times.

Example :

[
    {
        "2019-02-17T00:00:00-08:00": {//Date
            "2019-02-17T10:00:00+02:00": {//StartTimeLocalized
                "2019-02-17T19:00:00+02:00": {//EndTimeLocalized
                    "[NYC] Network - Solutions": {//LabelWithCompany
                        "attendees": [
                            "att_name1",//AttendeeDisplayName
                            "att_name2"  //AttendeeDisplayName    
                        ]
                    }
                }
            }
        }
    }
]

I assume that map and reduce are the necessary functions, but I had trouble with doing multiple nested reduces. Any other suggestion how to aggregate these objects to into an aggregated format that will contain all the attendees for each session.


回答1:


You could take some helper function for getting the value of a nested object and for setting a path and returning the last nested object by taking an array of keys.

Then you need to take the keys for the nested result set an another for getting the value for pushing to the result.

const
    getValue = (object, path) => [].concat(path).reduce((o, k) => o[k], object),
    setPath = (object, path) => [].concat(path).reduce((o, k) => o[k] = o[k] || {}, object);

var data = [{ Id: 79, Date: "2018-08-27T00:00:00-07:00", StartTime: 1535385600, EndTime: 1535416200, Slots: [{ blnEmptySlot: false, strType: "B", intStart: 3600, intEnd: 5400, intUnixStart: 1535389200, intUnixEnd: 1535391000 }], OperationalUnit: 3, Created: "2019-01-31T11:23:29+02:00", StartTimeLocalized: "2019-02-17T10:00:00+02:00", EndTimeLocalized: "2019-02-17T19:00:00+02:00", _MetaData: { AttendeeInfo: { Id: 111, AttendeeDisplayName: "att_name1", AttendeeProfile: 406, Attendee: 406, Photo: "avatar_path" }, OperationalUnitInfo: { Id: 3, OperationalUnitName: "op_unit_name", Company: 1, CompanyName: "comp_name", LabelWithCompany: "comp_label" } } }, { Id: 80, Date: "2018-08-27T00:00:00-07:00", StartTime: 1535385600, EndTime: 1535416200, Slots: [{ blnEmptySlot: false, strType: "B", intStart: 3600, intEnd: 5400, intUnixStart: 1535389200, intUnixEnd: 1535391000 }], OperationalUnit: 3, Created: "2019-01-31T11:23:29+02:00", StartTimeLocalized: "2019-02-17T10:00:00+02:00", EndTimeLocalized: "2019-02-17T19:00:00+02:00", _MetaData: { AttendeeInfo: { Id: 112, AttendeeDisplayName: "att_name2", AttendeeProfile: 407, Attendee: 407, Photo: "avatar_path" }, OperationalUnitInfo: { Id: 3, OperationalUnitName: "op_unit_name", Company: 1, CompanyName: "comp_name", LabelWithCompany: "comp_label" } } }],
    keys = ["Date", "StartTimeLocalized", "EndTimeLocalized", ["_MetaData", "OperationalUnitInfo", "LabelWithCompany"]],
    value = ["_MetaData", "AttendeeInfo", "AttendeeDisplayName"],
    result = data.reduce((r, o) => {
        var temp = setPath(r, keys.map(getValue.bind(null, o)));

        temp.attendees = temp.attendees || [];
        temp.attendees.push(getValue(o, value));
        return r;
    }, {});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }



回答2:


You could define a function to ease the creation of the hierarchy (drill), and then iterate over the records, like this:

const data = [{"Id": 79,"Date": "2019-02-17T00:00:00-07:00","StartTime": 1535385600,"EndTime": 1535416200,"Slots": [{"blnEmptySlot": false,"strType": "B","intStart": 3600,"intEnd": 5400,"intUnixStart": 1535389200,"intUnixEnd": 1535391000,}],"OperationalUnit": 3,"Created": "2019-01-31T11:23:29+02:00","StartTimeLocalized": "2019-02-17T10:00:00+02:00","EndTimeLocalized": "2019-02-17T19:00:00+02:00","_MetaData": {"AttendeeInfo": {"Id": 111,"AttendeeDisplayName": "att_name1","AttendeeProfile": 406,"Attendee": 406,"Photo": "avatar_path"},"OperationalUnitInfo": {"Id": 3,"OperationalUnitName": "op_unit_name","Company": 1,"CompanyName": "comp_name","LabelWithCompany": "comp_label"},}},{"Id": 80,"Date": "2019-02-17T00:00:00-07:00","StartTime": 1535385600,"EndTime": 1535416200,"Slots": [{"blnEmptySlot": false,"strType": "B","intStart": 3600,"intEnd": 5400,"intUnixStart": 1535389200,"intUnixEnd": 1535391000,}],"OperationalUnit": 3,"Created": "2019-01-31T11:23:29+02:00","StartTimeLocalized": "2019-02-17T10:00:00+02:00","EndTimeLocalized": "2019-02-17T19:00:00+02:00","_MetaData": {"AttendeeInfo": {"Id": 112,"AttendeeDisplayName": "att_name2","AttendeeProfile": 407,"Attendee": 407,"Photo": "avatar_path"},"OperationalUnitInfo": {"Id": 3,"OperationalUnitName": "op_unit_name","Company": 1,"CompanyName": "comp_name","LabelWithCompany": "comp_label"},}}];

const drill = (o, key, ...keys) => key ? drill(o[key] = o[key] || {}, ...keys) : o; 

const result = {};    
for (const e of data) {
    const key = drill(result, e.Date, 
                              e.StartTimeLocalized, 
                              e.EndTimeLocalized, 
                              e._MetaData.OperationalUnitInfo.LabelWithCompany);
    key.attendees = (key.attendees || []).concat(
                              e._MetaData.AttendeeInfo.AttendeeDisplayName);
}

console.log(result);

NB: there seems no use to wrap the output in an array, but you can of course do that.



来源:https://stackoverflow.com/questions/54987567/js-reduce-and-group-json-by-deeply-nested-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!