javascript - 如何从 JSON 数据构建树?通过使用任何编程语言修改如下所示的条目
问题描述
输入:
const data = [
{
category: 'Techonology',
subcategory: 'laptop',
sale: 19000,
profit: 909049,
},
{
category: 'Furniture',
subcategory: 'badge',
sale: 2009900,
profit: 699600,
},
{
category: 'Techonology',
subcategory: 'chair',
sale: 30000,
profit: 500,
},
{
category: 'Furniture',
subcategory: 'bed',
sale: 400,
profit: 200000,
},
]
输出应如下所示:
{
"name": "data",
"children": [
{
"name": "Techonology",
"children": [
{
"name": "laptop",
"children": [
{
"name": "sale",
"value": 19000
}
]
},
{
"name": "chair",
"children": [
{
"name": "sale",
"value": 30000
}
]
}
]
},
{
"name": "Furniture",
"children": [
{
"name": "badge",
"children": [
{
"name": "sale",
"value": 2009900
}
]
},
{
"name": "bed",
"children": [
{
"name": "sale",
"value": 400
}
]
}
]
}
]
}
解决方案
我假设您从某个站点获取数据,该结构已经定义并且无法更改。我建议您将结构更改为更易于管理的另一种方法。
无论如何,无论是否遵循你的结构,当你需要构建一棵树时,你必须递归地工作,以获得最深的结构并正确定义你需要的东西。
请记住这一点:
- 在您的结构中,每个项目只有一个子类别,但您可以拥有许多具有相同父类别的条目,其中唯一的变化是子类别元素,这不是最优的。
- 由于结构已经定义,我认为最好在武装树结构之前对其进行处理和重新排序
- 为了获得一个完整的示例,我修改了您的数据结构,添加了两个子元素,因为您拥有的一些“子类别”没有出现在那里。
所以,我使用的结构是:
var data1 = [
{
category: 'Techonology',
subcategory: 'laptop',
sale: 19000,
profit: 909049,
},
{
category: 'badge',
sale: 19000,
profit: 909049,
},
{
category: 'childrenchair',
sale: 19000,
profit: 909049,
},
{
category: 'chair',
subcategory: 'childrenchair',
sale: 19000,
profit: 909049,
},
{
category: 'Furniture',
subcategory: 'badge',
sale: 2009900,
profit: 699600,
},
{
category: 'Techonology',
subcategory: 'chair',
sale: 30000,
profit: 500,
},
{
category: 'Furniture',
subcategory: 'bed',
sale: 400,
profit: 200000,
},
]
下面的代码定义了树结构:
// loops the data to get all subcategory elements, this is used to
// avoid unnecessary iterations.
allChildren = data1.map(item=> item.subcategory).filter(item => !!item);
// this map has the data with the structure we need
preparedData = new Map()
data1.forEach(item => {
console.log(1, item.category, item.subcategory);
const data = preparedData.get(item.category) ?? {children: []};
data.isChildren = allChildren.includes(item.category);
if(item.subcategory) data.children.push(item.subcategory);
preparedData.set(item.category, Object.assign(item, data));
});
tree = [];
/**
getChildren method is recursive, it will be called for each category or subcategory with children's (recursively)
*/
getChildren = item=> {
const children = item.children.filter(item=> {
if(!preparedData.has(item)) return;
const data = preparedData.get(item);
const {category: name, sale, profit} = data;
subchildren = data.children.length ? getChildren(item) : [];
return {name, sale, profit, children: subchildren};
});
return children;
};
// loop the data
preparedData.forEach(item=>{
// it the item has the property isChildren as true, then is a subcategory and
// is not necessary to check it in the first level of the tree
if(item.isChildren) return;
const {category: name, sale, profit} = item;
children = item.children.length ? getChildren(item) : [];
tree.push({name, sale, profit, children});
});
我在 devtools 控制台中检查了此代码并运行,您可以将其复制并粘贴以进行检查,然后进行所需的调整
推荐阅读
- ruby-on-rails - 我的 Rails 按钮没有更新数据库
- elasticsearch - 如何将弹性搜索数据重新索引到新的映射(从平面字段到对象)?
- r - 函数R中的forloops问题
- c# - 使用 Import-Module 导入时,C# 二进制文件中的 Cmdlet 不导出
- ngx-datatable - 带有滚动条的页面限制V
- flutter - 使用 Navigator.push (MaterialPageRoute) 而不是 AlertDialog
- html - 如何在 pickerInput 中对选定的值进行文本换行(来自 shinyWidgets 包)。使选择器的高度改变以适应多行
- python - 更改特定路径中文件的“用户”
- kubernetes - 如何使用大使网关路由或 cloudflare 检测浏览器?
- multithreading - 有没有办法使用 MVar 在 haskell 中制作这个文本游戏?