我有一个对象数组:
const flatData = [
{
"name": "Fish 1",
"price": 15
},
{
"name": "Super Fish 1",
"price": 12,
"family": "Super Fish family"
},
{
"name": "Super Fish 2",
"price": 17,
"family": "Super Fish family"
},
{
"name": "Super Fish 3",
"price": 16,
"family": "Super Fish family"
},
{
"name": "Awful legged Fish 1",
"price": 22,
"family": "Awful Fish family",
"sub_family": "Awful Fish with legs"
},
{
"name": "Awful legged Fish 2",
"price": 15,
"family": "Awful Fish family",
"sub_family": "Awful Fish with legs"
},
{
"name": "Awful legged Fish 3",
"price": 23,
"family": "Awful Fish family",
"sub_family": "Awful Fish with legs"
},
{
"name": "Awful blue dotted Fish 1",
"price": 10,
"family": "Awful Fish family",
"sub_family": "Awful Fish with blue dots"
},
{
"name": "Awful blue dotted Fish 2",
"price": 11,
"family": "Awful Fish family",
"sub_family": "Awful Fish with blue dots"
}
]
我想将其转换为嵌套的对象数组:
const nestedData = [
{
"id": "0",
"name": "Fish 1",
"price": 15
},
{
"id": "1",
"name": "Super Fish family",
"selected": -1,
"family": [
{
"id": "0",
"name": "Super Fish 1",
"price": 12
},
{
"id": "1",
"name": "Super Fish 2",
"price": 17
},
{
"id": "2",
"name": "Super Fish 3",
"price": 16
}
]
},
{
"id": "2",
"name": "Awful Fish family",
"selected": -1,
"family": [
{
"id": "0",
"name": "Awful Fish with legs",
"selected": -1,
"family": [
{
"id": "0",
"name": "Awful legged Fish 1",
"price": 22
},
{
"id": "1",
"name": "Awful legged Fish 2",
"price": 15
},
{
"id": "2",
"name": "Awful legged Fish 3",
"price": 23
}
]
},
{
"id": "1",
"name": "Awful Fish with blue dots",
"selected": -1,
"family": [
{
"id": "0",
"name": "Awful blue dotted Fish 1",
"price": 10
},
{
"id": "1",
"name": "Awful blue dotted Fish 2",
"price": 11
}
]
}
]
}
]
我以为我可以将问题分解为一系列不太复杂的问题,但我被困在这一步了。我找到了基于拆分字符串的解决方案,但我的平面文件不同。 “family”和“sub_family”的存在,我可以从一个值推断出深度信息......
有没有一个js库可以让这变得更容易?
嗯,基于类似的答案,我或多或少添加了一些属性来适应相同的解决方案。
const flatData = [{
"name": "Fish 1",
"price": 15
},
{
"name": "Super Fish 1",
"price": 12,
"family": "Super Fish family"
},
{
"name": "Super Fish 2",
"price": 17,
"family": "Super Fish family"
},
{
"name": "Super Fish 3",
"price": 16,
"family": "Super Fish family"
},
{
"name": "Awful legged Fish 1",
"price": 22,
"family": "Awful Fish family",
"sub_family": "Awful Fish with legs"
},
{
"name": "Awful legged Fish 2",
"price": 15,
"family": "Awful Fish family",
"sub_family": "Awful Fish with legs"
},
{
"name": "Awful legged Fish 3",
"price": 23,
"family": "Awful Fish family",
"sub_family": "Awful Fish with legs"
},
{
"name": "Awful blue dotted Fish 1",
"price": 10,
"family": "Awful Fish family",
"sub_family": "Awful Fish with blue dots"
},
{
"name": "Awful blue dotted Fish 2",
"price": 11,
"family": "Awful Fish family",
"sub_family": "Awful Fish with blue dots"
}
]
function unflatten(arr) {
var tree = []
// create helper property of ancestry as array
arr.map(function(item) {
item.idPathOfEntityToAttribute = []
item.family && item.idPathOfEntityToAttribute.push(item.family)
item.sub_family && item.idPathOfEntityToAttribute.push(item.sub_family)
item.idPathOfEntityToAttribute.push(item.name)
delete item.family
delete item.sub_family
return item
})
// group by name for easy access
var grouped = arr.reduce(function(agg, item) {
agg[item.name] = item
item.selected = -1
item.family = []
// make sure item path exists
var path = [...item.idPathOfEntityToAttribute]
var so_far = []
while (path.length) {
var parent = path.shift()
so_far.push(parent)
if (!agg[parent]) {
agg[parent] = {
name: parent,
selected: -1,
family: [],
idPathOfEntityToAttribute: [...so_far]
}
}
}
return agg;
}, {})
Object.keys(grouped).forEach(function(key) {
var item = grouped[key];
// attach to the tree or to the parent
var len = item.idPathOfEntityToAttribute.length
var parent_id = len > 1 ? item.idPathOfEntityToAttribute[len - 2] : null
if (parent_id) {
var parent = grouped[parent_id]
parent.family.push(item);
} else {
tree.push(item)
}
})
// optionally clean by removing idPathOfEntityToAttribute
Object.keys(grouped).forEach(function(key) {
var item = grouped[key];
if (!item.family.length) {
delete item.family
delete item.selected
}
delete item.idPathOfEntityToAttribute
})
// adding index property
add_indexes(tree)
return tree;
}
function add_indexes(tree) {
for (var i = 0; i < tree.length; i++) {
var item = tree[i]
tree[i] = {
id: "" + i,
...item
}
if (item.family) {
add_indexes(item.family)
}
}
}
var tree = unflatten(flatData)
console.log(tree)
.as-console-wrapper {
max-height: 100% !important;
min-height: 100% !important;
}