如何基于普通对象创建嵌套数组
How to create a nested array based on a plain object
我有一个以下列格式输出数据的端点:
const result = [
{id: 4, parentId: null, name: 'Fruits & Veggies'},
{id: 12, parentId: 133, name: 'Sanguinello'},
{id: 3, parentId: 4, name: 'Fruits'},
{id: 67, parentId: 98, name: 'Sesame'},
{id: 23, parentId: 3, name: 'Orange'},
{id: 7, parentId: null, name: 'Grains'},
{id: 134, parentId: 7, name: 'Flour'},
{id: 3512, parentId: 23, name: 'Navel Orange'},
{id: 98, parentId: null, name: 'Seeds'},
{id: 4122, parentId: 58, name: 'Lamb'},
{id: 133, parentId: 23, name: 'Blood Orange'},
];
并且我需要创建一个递归函数来获取一个潜在的无限嵌套对象,其格式应如下所示:
const infiniteTreeOutput = {
children: [
{ label: 'Fruits & Veggies', id: 4, children: [
{ label: 'Fruits', id: 3, children: [
{ label: 'Orange', id: 23, children: [
{ label: 'Navel Orange', id: 3512 },
{ label: 'Blood Orange', id: 133, children: [
{ label: 'Sanguinello', id: 12 }
]
}
]
}
]
}
]
},
{ label: 'Grains', id: 7 },
{ label: 'Seeds', id: 98, children: [
{ label: 'Sesame', id: 67 }
]
}
]
};
所以:
- 如果 parentId 为 null,则它们位于顶层(水果和蔬菜、谷物、种子)。
- 如果给定节点没有子节点,那么它根本不应该有那个 属性。
- 如果有孤立数据(比如 'Lamb' 这里我们没有它的父对象,那么我们应该忽略那个对象)。
我有一个糟糕的工作函数,但我很想知道是否可以有一个递归解决方案。
您可以采用没有递归的简单单循环方法,但使用一个对象来保留所有节点。
const
data = [{ id: 4, parentId: null, name: 'Fruits & Veggies' }, { id: 12, parentId: 133, name: 'Sanguinello' }, { id: 3, parentId: 4, name: 'Fruits' }, { id: 67, parentId: 98, name: 'Sesame' }, { id: 23, parentId: 3, name: 'Orange' }, { id: 7, parentId: null, name: 'Grains' }, { id: 134, parentId: 7, name: 'Flour' }, { id: 3512, parentId: 23, name: 'Navel Orange' }, { id: 98, parentId: null, name: 'Seeds' }, { id: 133, parentId: 23, name: 'Blood Orange' }],
tree = function (data, root) {
var t = {};
data.forEach(({ id, parentId, name: label }) => {
Object.assign(t[id] = t[id] || {}, { label, id });
((t[parentId] ??= { label: '', id: null, }).children ??= []).push(t[id]);
});
return t[root].children;
}(data, null);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我有一个以下列格式输出数据的端点:
const result = [
{id: 4, parentId: null, name: 'Fruits & Veggies'},
{id: 12, parentId: 133, name: 'Sanguinello'},
{id: 3, parentId: 4, name: 'Fruits'},
{id: 67, parentId: 98, name: 'Sesame'},
{id: 23, parentId: 3, name: 'Orange'},
{id: 7, parentId: null, name: 'Grains'},
{id: 134, parentId: 7, name: 'Flour'},
{id: 3512, parentId: 23, name: 'Navel Orange'},
{id: 98, parentId: null, name: 'Seeds'},
{id: 4122, parentId: 58, name: 'Lamb'},
{id: 133, parentId: 23, name: 'Blood Orange'},
];
并且我需要创建一个递归函数来获取一个潜在的无限嵌套对象,其格式应如下所示:
const infiniteTreeOutput = {
children: [
{ label: 'Fruits & Veggies', id: 4, children: [
{ label: 'Fruits', id: 3, children: [
{ label: 'Orange', id: 23, children: [
{ label: 'Navel Orange', id: 3512 },
{ label: 'Blood Orange', id: 133, children: [
{ label: 'Sanguinello', id: 12 }
]
}
]
}
]
}
]
},
{ label: 'Grains', id: 7 },
{ label: 'Seeds', id: 98, children: [
{ label: 'Sesame', id: 67 }
]
}
]
};
所以:
- 如果 parentId 为 null,则它们位于顶层(水果和蔬菜、谷物、种子)。
- 如果给定节点没有子节点,那么它根本不应该有那个 属性。
- 如果有孤立数据(比如 'Lamb' 这里我们没有它的父对象,那么我们应该忽略那个对象)。
我有一个糟糕的工作函数,但我很想知道是否可以有一个递归解决方案。
您可以采用没有递归的简单单循环方法,但使用一个对象来保留所有节点。
const
data = [{ id: 4, parentId: null, name: 'Fruits & Veggies' }, { id: 12, parentId: 133, name: 'Sanguinello' }, { id: 3, parentId: 4, name: 'Fruits' }, { id: 67, parentId: 98, name: 'Sesame' }, { id: 23, parentId: 3, name: 'Orange' }, { id: 7, parentId: null, name: 'Grains' }, { id: 134, parentId: 7, name: 'Flour' }, { id: 3512, parentId: 23, name: 'Navel Orange' }, { id: 98, parentId: null, name: 'Seeds' }, { id: 133, parentId: 23, name: 'Blood Orange' }],
tree = function (data, root) {
var t = {};
data.forEach(({ id, parentId, name: label }) => {
Object.assign(t[id] = t[id] || {}, { label, id });
((t[parentId] ??= { label: '', id: null, }).children ??= []).push(t[id]);
});
return t[root].children;
}(data, null);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }