我试图建立一个树下所有独特路径的列表/ 多维对象数组。
假设这个数据......
const data = [
{
id: '1',
items: [
{
id: '1.1',
items: [ { id: '1.1.1' }, { id: '1.1.2' }, { id: '1.1.3' }, ]
}
]
},
{
id: '2',
items: [
{
id: '2.1',
items: [ { id: '2.1.1' }, { id: '2.1.2' }, { id: '2.1.3' }, ]
},
{
id: '2.2',
items: [ { id: '2.2.1' } ]
}
]
}
]
我需要最终得到像这样的数组结构..
const result = [
['1', '1.1', '1.1.1'],
['1', '1.1', '1.1.2'],
['1', '1.1', '1.1.3'],
['2', '2.1', '2.1.1'],
['2', '2.1', '2.1.2'],
['2', '2.1', '2.1.3'],
['2', '2.2', '2.2.1']
];
每个条目都是原始树结构中唯一path
的数组。
我很难将每条路径作为单独的条目。到目前为止,我将它们返回到较低级别的路径,并将底层ID附加到当前路径。
function flatten(items, path = []) {
let result = [];
items.forEach( item => {
path.push(item.id);
if (item.items && item.items.length) {
result.push(flatten(item.items, path.slice(0) )); //slice to clone the array
}
else {
result.push(...path);
}
});
return result;
}
这是一个JS小提琴......
答案 0 :(得分:1)
您可以使用reduce()
方法创建递归函数并返回数组。您可以使用concat()
方法创建prev
数组的副本,以便在每个递归级别上都有新副本,因为数组是通过引用传递的,否则您将更改原始数组。
const data = [{"id":"1","items":[{"id":"1.1","items":[{"id":"1.1.1"},{"id":"1.1.2"},{"id":"1.1.3"}]}]},{"id":"2","items":[{"id":"2.1","items":[{"id":"2.1.1"},{"id":"2.1.2"},{"id":"2.1.3"}]},{"id":"2.2","items":[{"id":"2.2.1"}]}]}]
function build(data, prev = []) {
return data.reduce(function(r, e) {
const copy = prev.concat(e.id)
if (e.items) r = r.concat(build(e.items, copy))
else r.push(copy)
return r;
}, [])
}
const result = build(data);
console.log(result)
答案 1 :(得分:0)
共享foreach回调中的更新路径。它应该是本地的。
function flatten(items, path = []) {
let result = [];
items.forEach(item => {
let localPath = path.slice(0);
localPath.push(item.id);
if (item.items && item.items.length) {
result.push(flatten(item.items, localPath));
} else {
result.push(localPath);
}
});
return result;
}
答案 2 :(得分:0)
您可以使用将所有完整路径推送到同一结果数组的内部方法:
const data = [{"id":"1","items":[{"id":"1.1","items":[{"id":"1.1.1"},{"id":"1.1.2"},{"id":"1.1.3"}]}]},{"id":"2","items":[{"id":"2.1","items":[{"id":"2.1.1"},{"id":"2.1.2"},{"id":"2.1.3"}]},{"id":"2.2","items":[{"id":"2.2.1"}]}]}]
function flatten(items) {
const result = [];
const iterateItems = (items, path = []) =>
items.forEach(({ id, items }) => {
const localPath = [...path, id];
if (items)
iterateItems(items, localPath);
else
result.push(localPath);
});
iterateItems(items);
return result;
}
console.log(flatten(data));
另一种选择是使用Array.map()
,并将每个阶段的结果按spreading展平为Array.concat()
:
const data = [{"id":"1","items":[{"id":"1.1","items":[{"id":"1.1.1"},{"id":"1.1.2"},{"id":"1.1.3"}]}]},{"id":"2","items":[{"id":"2.1","items":[{"id":"2.1.1"},{"id":"2.1.2"},{"id":"2.1.3"}]},{"id":"2.2","items":[{"id":"2.2.1"}]}]}];
const flatten = (arr, path = []) =>
[].concat(...arr.map(({ id, items }) => items ?
flatten(items, [...path, id]) : [[...path, id]]
));
const result = flatten(data);
console.log(result);