按后代和祖先将列表转换为树
Convert list to tree by descendants and ancestors
我正在尝试使用元素中的后代和祖先参数将列表转换为树:
我有这样的例子:
const itemToUpdate = {
id: 1,
ancestors: [
{
id: 2,
ancestors: [
{
id: 4
}
]
}
],
descendants: [
{
id: 3,
descendants: [
{
id: 5
},
{
id: 6,
descendants: [
{
id: 8
},
{
id: 9
}
]
},
{
id: 7
}
]
}
]
};
const updatedItem = {
id: 4,
children: [
{
id: 2,
children: [
{
id: 1,
children: [
{
id: 3,
children: [
{
id: 5
},
{
id: 6,
children: [
{
id: 8
},
{
id: 9
}
]
},
{
id: 7
}
]
}
]
}
]
}
]
};
关键是树可以嵌套到很多层。此外,关卡上可以有很多祖先和后代,所以我需要一个更通用的解决方案。必须从祖先向上创建树,从后代向下创建树。
我找到了获取树的后代的方法,但我仍然需要在这棵树的顶部添加祖先:
export const convertListToTree = <T extends ApiTree<T>>(list: Array<T>, key = 'ascendants'): Array<T> => {
const getNestedItem = (path: Array<string>, tree: Array<T>): T => {
const nestedItem = tree.find(nestedItem => nestedItem.id === path[0]);
const newPath = path.slice(1);
if (!newPath.length) {
return nestedItem;
} else if (nestedItem?.[key]) {
return getNestedItem(newPath, nestedItem?.[key]);
} else {
return getNestedItem(newPath, tree);
}
};
const sortListByPathLength = (list: Array<T>): Array<T> => {
return sortBy(list, (item: T) => item.path?.length);
};
const addRootItem = (item: T, tree: Array<T>): void => {
tree.push(item);
};
const addChildrenItem = (item: T, tree: Array<T>): void => {
const parent = getNestedItem(item.path, tree);
if (parent) {
parent[key].push(item);
} else {
addRootItem(item, tree);
}
};
const tree = [];
if (list?.length) {
const sortedList = sortListByPathLength(list);
sortedList.forEach(item => {
if (!item.path?.length) {
addRootItem(item, tree);
} else {
addChildrenItem(item, tree);
}
});
}
return tree;
};
我们非常欢迎任何建议。
我不太确定你想在那里实现什么。你能再详细一点吗?
如果有帮助,这就是您转换特定示例的方式。
function convert(item) {
return {
id: item.ancestors[0].id,
children: [
{
id: item.id,
children: [
{
id: item.descendants[0].id
}
]
}
]
}
}
假设每个级别只有 一个祖先节点,您可以采用递归函数保留子节点,但 returns 最早的祖先节点。
const
fn = ({ id, ancestors, descendants }, children) => {
const node = { id };
if (Array.isArray(children)) node.children = children;
if (descendants) node.children = descendants.map(fn);
return ancestors
? fn(ancestors[0], [node])
: node;
},
data = { id: 1, ancestors: [{ id: 2, ancestors: [{ id: 4 }] }], descendants: [{ id: 3, descendants: [{ id: 5 }] }] },
result = fn(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我正在尝试使用元素中的后代和祖先参数将列表转换为树:
我有这样的例子:
const itemToUpdate = {
id: 1,
ancestors: [
{
id: 2,
ancestors: [
{
id: 4
}
]
}
],
descendants: [
{
id: 3,
descendants: [
{
id: 5
},
{
id: 6,
descendants: [
{
id: 8
},
{
id: 9
}
]
},
{
id: 7
}
]
}
]
};
const updatedItem = {
id: 4,
children: [
{
id: 2,
children: [
{
id: 1,
children: [
{
id: 3,
children: [
{
id: 5
},
{
id: 6,
children: [
{
id: 8
},
{
id: 9
}
]
},
{
id: 7
}
]
}
]
}
]
}
]
};
关键是树可以嵌套到很多层。此外,关卡上可以有很多祖先和后代,所以我需要一个更通用的解决方案。必须从祖先向上创建树,从后代向下创建树。
我找到了获取树的后代的方法,但我仍然需要在这棵树的顶部添加祖先:
export const convertListToTree = <T extends ApiTree<T>>(list: Array<T>, key = 'ascendants'): Array<T> => {
const getNestedItem = (path: Array<string>, tree: Array<T>): T => {
const nestedItem = tree.find(nestedItem => nestedItem.id === path[0]);
const newPath = path.slice(1);
if (!newPath.length) {
return nestedItem;
} else if (nestedItem?.[key]) {
return getNestedItem(newPath, nestedItem?.[key]);
} else {
return getNestedItem(newPath, tree);
}
};
const sortListByPathLength = (list: Array<T>): Array<T> => {
return sortBy(list, (item: T) => item.path?.length);
};
const addRootItem = (item: T, tree: Array<T>): void => {
tree.push(item);
};
const addChildrenItem = (item: T, tree: Array<T>): void => {
const parent = getNestedItem(item.path, tree);
if (parent) {
parent[key].push(item);
} else {
addRootItem(item, tree);
}
};
const tree = [];
if (list?.length) {
const sortedList = sortListByPathLength(list);
sortedList.forEach(item => {
if (!item.path?.length) {
addRootItem(item, tree);
} else {
addChildrenItem(item, tree);
}
});
}
return tree;
};
我们非常欢迎任何建议。
我不太确定你想在那里实现什么。你能再详细一点吗?
如果有帮助,这就是您转换特定示例的方式。
function convert(item) {
return {
id: item.ancestors[0].id,
children: [
{
id: item.id,
children: [
{
id: item.descendants[0].id
}
]
}
]
}
}
假设每个级别只有 一个祖先节点,您可以采用递归函数保留子节点,但 returns 最早的祖先节点。
const
fn = ({ id, ancestors, descendants }, children) => {
const node = { id };
if (Array.isArray(children)) node.children = children;
if (descendants) node.children = descendants.map(fn);
return ancestors
? fn(ancestors[0], [node])
: node;
},
data = { id: 1, ancestors: [{ id: 2, ancestors: [{ id: 4 }] }], descendants: [{ id: 3, descendants: [{ id: 5 }] }] },
result = fn(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }