JS Reduce 和 group JSON by deeply nested object
JS Reduce and group JSON by deeply nested object
我正在通过 REST 拉取一个 JSON 对象数组,其中包含一些字段和一些嵌套对象。
我要创建的是一个来自具有以下结构的嵌套 JSON 对象数组的分组摘要对象:
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"
},
}
}
];
总体目的是创建一个包含开始和结束日期时间的事件对象列表、一个 LabelWithCompany 字符串(深层嵌套对象)和一个按 OperationalUnitName 以及开始和结束时间分组的所有参加者的列表。
示例:
[
{
"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
]
}
}
}
}
}
]
我假设 map 和 reduce 是必要的函数,但我在执行多个嵌套的 reduce 时遇到了麻烦。
关于如何将这些对象聚合成聚合格式的任何其他建议,该格式将包含每个会话的所有与会者。
您可以使用一些辅助函数来获取嵌套对象的值并设置路径并通过获取键数组返回最后一个嵌套对象。
然后您需要将嵌套结果集的键与另一个键一起获取用于推送到结果的值。
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; }
您可以定义一个函数来简化层次结构的创建 (drill
),然后遍历记录,如下所示:
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);
注意:将输出包装在数组中似乎没有用,但您当然可以这样做。
我正在通过 REST 拉取一个 JSON 对象数组,其中包含一些字段和一些嵌套对象。
我要创建的是一个来自具有以下结构的嵌套 JSON 对象数组的分组摘要对象:
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"
},
}
}
];
总体目的是创建一个包含开始和结束日期时间的事件对象列表、一个 LabelWithCompany 字符串(深层嵌套对象)和一个按 OperationalUnitName 以及开始和结束时间分组的所有参加者的列表。
示例:
[
{
"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
]
}
}
}
}
}
]
我假设 map 和 reduce 是必要的函数,但我在执行多个嵌套的 reduce 时遇到了麻烦。 关于如何将这些对象聚合成聚合格式的任何其他建议,该格式将包含每个会话的所有与会者。
您可以使用一些辅助函数来获取嵌套对象的值并设置路径并通过获取键数组返回最后一个嵌套对象。
然后您需要将嵌套结果集的键与另一个键一起获取用于推送到结果的值。
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; }
您可以定义一个函数来简化层次结构的创建 (drill
),然后遍历记录,如下所示:
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);
注意:将输出包装在数组中似乎没有用,但您当然可以这样做。