使用 JavaScript 组合和分组数组
Combining and grouping arrays using JavaScript
我有两组数据需要以某种方式组合和分组。
第一组数据:
let overallCert =
[
{
"id": "1",
"entity_id": "3",
"status": "Certified",
},
{
"id": "379",
"entity_id": "417",
"status": "Certified",
}
];
第二组数据:
let userCerts =
[
{
"id": "640",
"entity_id": "417",
"method": "Field Study",
"strand": "",
"date_completed": "2016-07-15T08:00:00.000Z"
},
{
"id": "814",
"entity_id": "417",
"method": "Field Study",
"date_completed": "2019-07-15T08:00:00.000Z"
},
{
"id": "844",
"entity_id": "3",
"method": "Online",
"date_completed": "2022-03-28T08:00:00.000Z"
},
{
"id": "845",
"entity_id": "3",
"method": "Field Study",
"date_completed": "2022-03-28T08:00:00.000Z"
}
];
我想通过 entity_id
合并和分组这些对象数组以在下面创建此输出...
期望的输出:
let desiredOutput =
[
[
[
{
"id": "640",
"entity_id": "417",
"method": "Field Study",
"date_completed": "2016-07-15T08:00:00.000Z"
},
{
"id": "814",
"entity_id": "417",
"method": "Field Study",
"date_completed": "2019-07-15T08:00:00.000Z"
},
],
[
{
"id": "379",
"entity_id": "417",
"status": "Certified",
}
]
],
[
[
{
"id": "844",
"entity_id": "3",
"method": "Online",
"date_completed": "2022-03-28T08:00:00.000Z"
},
{
"id": "845",
"entity_id": "3",
"method": "Field Study",
"date_completed": "2022-03-28T08:00:00.000Z"
}
],
[
{
"id": "379",
"entity_id": "417",
"status": "Certified",
}
]
]
];
到目前为止,我已经做到了:
let certsDataCombined = overallCert.map(item => ({ ...item,
0 : userCerts.filter(c => c.entity_id == item.entity_id)
}));
let userCertsGroupBy = groupBy(certsDataCombined, "entity_id");
function groupBy(arr, prop) {
const map = new Map(Array.from(arr, obj => [obj[prop], []]));
arr.forEach(obj => map.get(obj[prop]).push(obj));
return Array.from(map.values());
}
这段代码几乎可以解决问题,但我需要将 overallCert
数据封装在它自己的数组中,而且嵌套有点偏离。 是当前输出:
似乎您可以通过将每个 overallCert
映射到一个新数组然后使用 filter
拉出匹配的 userCerts
来构建输出
const overallCert = [{"id":"1","entity_id":"3","status":"Certified"},{"id":"379","entity_id":"417","status":"Certified"}];
const userCerts = [{"id":"640","entity_id":"417","method":"Field Study","strand":"","date_completed":"2016-07-15T08:00:00.000Z"},{"id":"814","entity_id":"417","method":"Field Study","date_completed":"2019-07-15T08:00:00.000Z"},{"id":"844","entity_id":"3","method":"Online","date_completed":"2022-03-28T08:00:00.000Z"},{"id":"845","entity_id":"3","method":"Field Study","date_completed":"2022-03-28T08:00:00.000Z"}];
const result = overallCert.map(cert => [
userCerts.filter(({ entity_id }) => cert.entity_id === entity_id),
[ cert ]
]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; }
请注意,顺序是基于 overallCert
而不是您问题中的 userCerts
。
以上是 O(n^2) 的时间复杂度,这并不好。您可以通过首先按 entity_id
对 O(n) 对两个数组进行分组来改进这一点。这也可以让您像示例中那样按 userCerts
排序。
const overallCert = [{"id":"1","entity_id":"3","status":"Certified"},{"id":"379","entity_id":"417","status":"Certified"}];
const userCerts = [{"id":"640","entity_id":"417","method":"Field Study","strand":"","date_completed":"2016-07-15T08:00:00.000Z"},{"id":"814","entity_id":"417","method":"Field Study","date_completed":"2019-07-15T08:00:00.000Z"},{"id":"844","entity_id":"3","method":"Online","date_completed":"2022-03-28T08:00:00.000Z"},{"id":"845","entity_id":"3","method":"Field Study","date_completed":"2022-03-28T08:00:00.000Z"}];
// Helper function since Map is missing this
Map.prototype.getOrDefault = function(key, defaultValue) {
return (this.has(key) ? this : this.set(key, defaultValue)).get(key);
};
// Groups certs by entity_id
const reducer = (map, cert) => (
map.getOrDefault(cert.entity_id, []).push(cert),
map
);
const overallCertsByEntityId = overallCert.reduce(reducer, new Map());
const userCertByEntityId = userCerts.reduce(reducer, new Map());
const result = Array.from(userCertByEntityId, ([key, certs]) => [
certs,
overallCertsByEntityId.get(key)
]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; }
我有两组数据需要以某种方式组合和分组。
第一组数据:
let overallCert =
[
{
"id": "1",
"entity_id": "3",
"status": "Certified",
},
{
"id": "379",
"entity_id": "417",
"status": "Certified",
}
];
第二组数据:
let userCerts =
[
{
"id": "640",
"entity_id": "417",
"method": "Field Study",
"strand": "",
"date_completed": "2016-07-15T08:00:00.000Z"
},
{
"id": "814",
"entity_id": "417",
"method": "Field Study",
"date_completed": "2019-07-15T08:00:00.000Z"
},
{
"id": "844",
"entity_id": "3",
"method": "Online",
"date_completed": "2022-03-28T08:00:00.000Z"
},
{
"id": "845",
"entity_id": "3",
"method": "Field Study",
"date_completed": "2022-03-28T08:00:00.000Z"
}
];
我想通过 entity_id
合并和分组这些对象数组以在下面创建此输出...
期望的输出:
let desiredOutput =
[
[
[
{
"id": "640",
"entity_id": "417",
"method": "Field Study",
"date_completed": "2016-07-15T08:00:00.000Z"
},
{
"id": "814",
"entity_id": "417",
"method": "Field Study",
"date_completed": "2019-07-15T08:00:00.000Z"
},
],
[
{
"id": "379",
"entity_id": "417",
"status": "Certified",
}
]
],
[
[
{
"id": "844",
"entity_id": "3",
"method": "Online",
"date_completed": "2022-03-28T08:00:00.000Z"
},
{
"id": "845",
"entity_id": "3",
"method": "Field Study",
"date_completed": "2022-03-28T08:00:00.000Z"
}
],
[
{
"id": "379",
"entity_id": "417",
"status": "Certified",
}
]
]
];
到目前为止,我已经做到了:
let certsDataCombined = overallCert.map(item => ({ ...item,
0 : userCerts.filter(c => c.entity_id == item.entity_id)
}));
let userCertsGroupBy = groupBy(certsDataCombined, "entity_id");
function groupBy(arr, prop) {
const map = new Map(Array.from(arr, obj => [obj[prop], []]));
arr.forEach(obj => map.get(obj[prop]).push(obj));
return Array.from(map.values());
}
这段代码几乎可以解决问题,但我需要将 overallCert
数据封装在它自己的数组中,而且嵌套有点偏离。
似乎您可以通过将每个 overallCert
映射到一个新数组然后使用 filter
userCerts
来构建输出
const overallCert = [{"id":"1","entity_id":"3","status":"Certified"},{"id":"379","entity_id":"417","status":"Certified"}];
const userCerts = [{"id":"640","entity_id":"417","method":"Field Study","strand":"","date_completed":"2016-07-15T08:00:00.000Z"},{"id":"814","entity_id":"417","method":"Field Study","date_completed":"2019-07-15T08:00:00.000Z"},{"id":"844","entity_id":"3","method":"Online","date_completed":"2022-03-28T08:00:00.000Z"},{"id":"845","entity_id":"3","method":"Field Study","date_completed":"2022-03-28T08:00:00.000Z"}];
const result = overallCert.map(cert => [
userCerts.filter(({ entity_id }) => cert.entity_id === entity_id),
[ cert ]
]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; }
请注意,顺序是基于 overallCert
而不是您问题中的 userCerts
。
以上是 O(n^2) 的时间复杂度,这并不好。您可以通过首先按 entity_id
对 O(n) 对两个数组进行分组来改进这一点。这也可以让您像示例中那样按 userCerts
排序。
const overallCert = [{"id":"1","entity_id":"3","status":"Certified"},{"id":"379","entity_id":"417","status":"Certified"}];
const userCerts = [{"id":"640","entity_id":"417","method":"Field Study","strand":"","date_completed":"2016-07-15T08:00:00.000Z"},{"id":"814","entity_id":"417","method":"Field Study","date_completed":"2019-07-15T08:00:00.000Z"},{"id":"844","entity_id":"3","method":"Online","date_completed":"2022-03-28T08:00:00.000Z"},{"id":"845","entity_id":"3","method":"Field Study","date_completed":"2022-03-28T08:00:00.000Z"}];
// Helper function since Map is missing this
Map.prototype.getOrDefault = function(key, defaultValue) {
return (this.has(key) ? this : this.set(key, defaultValue)).get(key);
};
// Groups certs by entity_id
const reducer = (map, cert) => (
map.getOrDefault(cert.entity_id, []).push(cert),
map
);
const overallCertsByEntityId = overallCert.reduce(reducer, new Map());
const userCertByEntityId = userCerts.reduce(reducer, new Map());
const result = Array.from(userCertByEntityId, ([key, certs]) => [
certs,
overallCertsByEntityId.get(key)
]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; }