javascript - 从对象数组和javascript中的维度列表创建父子结构
问题描述
我按州、城市和产品从 mysql 表组中获取了销售数据。我使用以下查询从 MySql 表中获取数据
select state,city,product,sales from salesTable group by state,city,product;
并从查询中得到以下输出,
[
{
"state": "S1",
"city": "CITY1",
"product": "P1",
"sales": 1000
},
{
"state": "S1",
"city": "CITY2",
"product": "P1",
"sales": 2000
},
{
"state": "S1",
"city": "CITY1",
"product": "P2",
"sales": 2000
},
{
"state": "S2",
"city": "CITY1",
"product": "P1",
"sales": 1000
},
{
"state": "S2",
"city": "CITY2",
"product": "P1",
"sales": 2000
},
{
"state": "S2",
"city": "CITY2",
"product": "P2",
"sales": 2000
},
{
"state": "S3",
"city": "CITY1",
"product": "P2",
"sales": 1000
},
{
"state": "S3",
"city": "CITY2",
"product": "P2",
"sales": 2000
}
]
现在我想创建父子结构,dimensions=["state","city","product"]
其中州是祖父母,城市是父母(州的孩子),产品是孩子。
如果维度数组应该是动态的,它的长度可能会增加或减少。
我需要波纹管输出,
[
{
"sales": 5000,
"state": "S1",
"children": [
{
"sales": 3000,
"state": "S1",
"city": "CITY1",
"children": [
{
"sales": 1000,
"state": "S1",
"city": "CITY1",
"product": "P1"
},
{
"sales": 2000,
"state": "S1",
"city": "CITY1",
"product": "P2"
}
]
},
{
"sales": 2000,
"state": "S1",
"city": "CITY2",
"children": [
{
"sales": 2000,
"state": "S1",
"city": "CITY2",
"children": [
{
"sales": 2000,
"state": "S1",
"city": "CITY2",
"product": "P1"
}
]
}
]
}
]
},
{
"sales": 5000,
"state": "S2",
"children": [
{
"sales": 1000,
"state": "S2",
"city": "CITY1",
"children": [
{
"sales": 1000,
"state": "S2",
"city": "CITY1",
"product": "P1"
}
]
},
{
"sales": 4000,
"state": "S2",
"city": "CITY2",
"children": [
{
"sales": 4000,
"state": "S2",
"city": "CITY2",
"children": [
{
"sales": 2000,
"state": "S2",
"city": "CITY2",
"product": "P1"
},
{
"sales": 2000,
"state": "S2",
"city": "CITY2",
"product": "P2"
}
]
}
]
}
]
},
{
"sales": 3000,
"state": "S3",
"children": [
{
"sales": 1000,
"state": "S3",
"city": "CITY1",
"children": [
{
"sales": 1000,
"state": "S3",
"city": "CITY1",
"product": "P2"
}
]
},
{
"sales": 2000,
"state": "S3",
"city": "CITY2",
"children": [
{
"sales": 2000,
"state": "S3",
"city": "CITY2",
"children": [
{
"sales": 2000,
"state": "S3",
"city": "CITY2",
"product": "P2"
}
]
}
]
}
]
}
]
解决方案
也许是这样的。在第一次迭代中,我们使用时间对象而不是数组来构建树,以便于分发。在第二次递归迭代中,我们从时间对象创建数组并计算销售额。
为了统一,最顶层也使用.children
key及其.sales
总和。这可以通过在末尾使用result.children
而不是忽略。result
const data = [
{ state: 'S1', city: 'CITY1', product: 'P1', sales: 1000 },
{ state: 'S1', city: 'CITY2', product: 'P1', sales: 2000 },
{ state: 'S1', city: 'CITY1', product: 'P2', sales: 2000 },
{ state: 'S2', city: 'CITY1', product: 'P1', sales: 1000 },
{ state: 'S2', city: 'CITY2', product: 'P1', sales: 2000 },
{ state: 'S2', city: 'CITY2', product: 'P2', sales: 2000 },
{ state: 'S3', city: 'CITY1', product: 'P2', sales: 1000 },
{ state: 'S3', city: 'CITY2', product: 'P2', sales: 2000 },
];
const dimensions = ['state', 'city', 'product'];
const childKey = dimensions[dimensions.length - 1];
const result = { children: Object.create(null) };
for (const entry of data) {
let parrent = null;
let current = result.children;
for (const dimension of dimensions) {
let slot = current[entry[dimension]];
if (!slot) {
slot = current[entry[dimension]] = Object.create(null);
slot.sales = dimension === childKey ? entry.sales : 0;
if (parrent) {
for (const [k, v] of Object.entries(parrent)) {
if (k !== 'children' && k !== 'sales') slot[k] = v;
}
}
slot[dimension] = entry[dimension];
if (dimension !== childKey) {
slot.children = Object.create(null);
}
}
parrent = slot;
current = slot.children;
}
}
normalizeAndSum(result, null);
console.log(JSON.stringify(result, null, ' '));
function normalizeAndSum(object, parent) {
if (object.children) {
object.children = Object.values(object.children);
for (const child of object.children) normalizeAndSum(child, object);
}
if (parent) {
parent.sales = parent.children.reduce((acc, { sales }) => acc + sales, 0);
}
}
推荐阅读
- ios - UITextField 更改后调用搜索 API,Moya
- clion - Clion:设置远程 Makefile 项目
- angular - 如何在角度中避免 *ngFor 循环中的空格?
- java - 使用 firebase 实时数据库,我的条目大约有 300 项。现在在 datasnapshot 中没有得到来自 firebase 的响应
- reactjs - 小型 Web 应用程序中的 501 Not Implemented 错误
- exception - WARN:oejw.WebAppContext:Thread-5113: 上下文 oejwWebAppContext-java.lang.NullPointerException 启动失败
- c++ - 不知道为什么会发生堆损坏(关于内存分配问题)
- java - 从多部分请求中读取表单数据
- java - ThreadPoolExecutor - 具有优先级和 FIFO 的 BlockingQueue
- c# - 如何禁用我的 postgresql 中的所有约束?