admin-vben5/packages/@vben-core/shared/toolkit/src/tree.ts
2024-05-19 21:20:42 +08:00

98 lines
2.5 KiB
TypeScript

interface TreeConfigOptions {
// 子属性的名称,默认为'children'
childProps: string;
}
/**
* @zh_CN 遍历树形结构,并返回所有节点中指定的值。
* @param tree 树形结构数组
* @param getValue 获取节点值的函数
* @param options 作为子节点数组的可选属性名称。
* @returns 所有节点中指定的值的数组
*/
function traverseTreeValues<T, V>(
tree: T[],
getValue: (node: T) => V,
options?: TreeConfigOptions,
): V[] {
const result: V[] = [];
const { childProps } = options || {
childProps: 'children',
};
const dfs = (treeNode: T) => {
const value = getValue(treeNode);
result.push(value);
const children = (treeNode as Record<string, any>)?.[childProps];
if (!children) {
return;
}
if (children.length > 0) {
for (const child of children) {
dfs(child);
}
}
};
for (const treeNode of tree) {
dfs(treeNode);
}
return result.filter(Boolean);
}
/**
* 根据条件过滤给定树结构的节点,并以原有顺序返回所有匹配节点的数组。
* @param tree 要过滤的树结构的根节点数组。
* @param filter 用于匹配每个节点的条件。
* @param options 作为子节点数组的可选属性名称。
* @returns 包含所有匹配节点的数组。
*/
function filterTree<T extends Record<string, any>>(
tree: T[],
filter: (node: T) => boolean,
options?: TreeConfigOptions,
): T[] {
const { childProps } = options || {
childProps: 'children',
};
const _filterTree = (nodes: T[]): T[] => {
return nodes.filter((node: Record<string, any>) => {
if (filter(node as T)) {
if (node[childProps]) {
node[childProps] = _filterTree(node[childProps]);
}
return true;
}
return false;
});
};
return _filterTree(tree);
}
/**
* 根据条件重新映射给定树结构的节
* @param tree 要过滤的树结构的根节点数组。
* @param mapper 用于map每个节点的条件。
* @param options 作为子节点数组的可选属性名称。
*/
function mapTree<T, V extends Record<string, any>>(
tree: T[],
mapper: (node: T) => V,
options?: TreeConfigOptions,
): V[] {
const { childProps } = options || {
childProps: 'children',
};
return tree.map((node) => {
const mapperNode: Record<string, any> = mapper(node);
if (mapperNode[childProps]) {
mapperNode[childProps] = mapTree(mapperNode[childProps], mapper, options);
}
return mapperNode as V;
});
}
export { filterTree, mapTree, traverseTreeValues };