tree.ts 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. interface TreeConfigOptions {
  2. // 子属性的名称,默认为'children'
  3. childProps: string;
  4. }
  5. /**
  6. * @zh_CN 遍历树形结构,并返回所有节点中指定的值。
  7. * @param tree 树形结构数组
  8. * @param getValue 获取节点值的函数
  9. * @param options 作为子节点数组的可选属性名称。
  10. * @returns 所有节点中指定的值的数组
  11. */
  12. function traverseTreeValues<T, V>(
  13. tree: T[],
  14. getValue: (node: T) => V,
  15. options?: TreeConfigOptions,
  16. ): V[] {
  17. const result: V[] = [];
  18. const { childProps } = options || {
  19. childProps: 'children',
  20. };
  21. const dfs = (treeNode: T) => {
  22. const value = getValue(treeNode);
  23. result.push(value);
  24. const children = (treeNode as Record<string, any>)?.[childProps];
  25. if (!children) {
  26. return;
  27. }
  28. if (children.length > 0) {
  29. for (const child of children) {
  30. dfs(child);
  31. }
  32. }
  33. };
  34. for (const treeNode of tree) {
  35. dfs(treeNode);
  36. }
  37. return result.filter(Boolean);
  38. }
  39. /**
  40. * 根据条件过滤给定树结构的节点,并以原有顺序返回所有匹配节点的数组。
  41. * @param tree 要过滤的树结构的根节点数组。
  42. * @param filter 用于匹配每个节点的条件。
  43. * @param options 作为子节点数组的可选属性名称。
  44. * @returns 包含所有匹配节点的数组。
  45. */
  46. function filterTree<T extends Record<string, any>>(
  47. tree: T[],
  48. filter: (node: T) => boolean,
  49. options?: TreeConfigOptions,
  50. ): T[] {
  51. const { childProps } = options || {
  52. childProps: 'children',
  53. };
  54. const _filterTree = (nodes: T[]): T[] => {
  55. return nodes.filter((node: Record<string, any>) => {
  56. if (filter(node as T)) {
  57. if (node[childProps]) {
  58. node[childProps] = _filterTree(node[childProps]);
  59. }
  60. return true;
  61. }
  62. return false;
  63. });
  64. };
  65. return _filterTree(tree);
  66. }
  67. /**
  68. * 根据条件重新映射给定树结构的节
  69. * @param tree 要过滤的树结构的根节点数组。
  70. * @param mapper 用于map每个节点的条件。
  71. * @param options 作为子节点数组的可选属性名称。
  72. */
  73. function mapTree<T, V extends Record<string, any>>(
  74. tree: T[],
  75. mapper: (node: T) => V,
  76. options?: TreeConfigOptions,
  77. ): V[] {
  78. const { childProps } = options || {
  79. childProps: 'children',
  80. };
  81. return tree.map((node) => {
  82. const mapperNode: Record<string, any> = mapper(node);
  83. if (mapperNode[childProps]) {
  84. mapperNode[childProps] = mapTree(mapperNode[childProps], mapper, options);
  85. }
  86. return mapperNode as V;
  87. });
  88. }
  89. export { filterTree, mapTree, traverseTreeValues };