TreeExtensions.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. namespace Masuit.Tools.Models
  5. {
  6. /// <summary>
  7. /// 树形数据扩展
  8. /// </summary>
  9. public static class TreeExtensions
  10. {
  11. /// <summary>
  12. /// 过滤
  13. /// </summary>
  14. /// <typeparam name="T"></typeparam>
  15. /// <param name="items"></param>
  16. /// <param name="func"></param>
  17. /// <returns></returns>
  18. public static IEnumerable<T> Filter<T>(this IEnumerable<T> items, Func<T, bool> func) where T : ITreeChildren<T>
  19. {
  20. var results = new List<T>();
  21. foreach (var item in items.Where(i => i != null))
  22. {
  23. item.Children = item.Children.Filter(func).ToList();
  24. if (item.Children.Any() || func(item))
  25. {
  26. results.Add(item);
  27. }
  28. }
  29. return results;
  30. }
  31. /// <summary>
  32. /// 过滤
  33. /// </summary>
  34. /// <typeparam name="T"></typeparam>
  35. /// <param name="item"></param>
  36. /// <param name="func"></param>
  37. /// <returns></returns>
  38. public static IEnumerable<T> Filter<T>(this T item, Func<T, bool> func) where T : ITreeChildren<T>
  39. {
  40. return new[] { item }.Filter(func);
  41. }
  42. /// <summary>
  43. /// 平铺开
  44. /// </summary>
  45. /// <typeparam name="T"></typeparam>
  46. /// <param name="items"></param>
  47. /// <returns></returns>
  48. public static IEnumerable<T> Flatten<T>(this IEnumerable<T> items) where T : ITreeChildren<T>
  49. {
  50. var result = new List<T>();
  51. foreach (var item in items)
  52. {
  53. result.Add(item);
  54. result.AddRange(item.Children.Flatten());
  55. }
  56. return result;
  57. }
  58. /// <summary>
  59. /// 平铺开任意树形结构数据
  60. /// </summary>
  61. /// <typeparam name="T"></typeparam>
  62. /// <param name="items"></param>
  63. /// <param name="selector"></param>
  64. /// <returns></returns>
  65. public static IEnumerable<T> Flatten<T>(this IEnumerable<T> items, Func<T, IEnumerable<T>> selector)
  66. {
  67. var result = new List<T>();
  68. foreach (var item in items)
  69. {
  70. result.Add(item);
  71. result.AddRange(selector(item).Flatten(selector));
  72. }
  73. return result;
  74. }
  75. /// <summary>
  76. /// 所有子级
  77. /// </summary>
  78. public static ICollection<T> AllChildren<T>(this ITreeChildren<T> tree) where T : ITreeChildren<T> => GetChildren(tree);
  79. /// <summary>
  80. /// 所有父级
  81. /// </summary>
  82. public static ICollection<T> AllParent<T>(this ITreeParent<T> tree) where T : ITreeParent<T> => GetParents(tree);
  83. /// <summary>
  84. /// 是否是根节点
  85. /// </summary>
  86. public static bool IsRoot<T>(this ITreeParent<T> tree) where T : ITreeParent<T> => tree.Parent == null;
  87. /// <summary>
  88. /// 是否是叶子节点
  89. /// </summary>
  90. public static bool IsLeaf<T>(this ITreeChildren<T> tree) where T : ITreeChildren<T> => tree.Children?.Count == 0;
  91. /// <summary>
  92. /// 深度层级
  93. /// </summary>
  94. public static int Level<T>(this ITreeParent<T> tree) where T : ITreeParent<T> => IsRoot(tree) ? 1 : Level(tree.Parent) + 1;
  95. /// <summary>
  96. /// 节点路径(UNIX路径格式,以“/”分隔)
  97. /// </summary>
  98. public static string Path<T>(this ITree<T> tree) where T : ITree<T> => GetFullPath(tree);
  99. private static string GetFullPath<T>(ITree<T> c) where T : ITree<T> => c.Parent != null ? GetFullPath(c.Parent) + "/" + c.Name : c.Name;
  100. /// <summary>
  101. /// 递归取出所有下级
  102. /// </summary>
  103. /// <param name="t"></param>
  104. /// <returns></returns>
  105. private static List<T> GetChildren<T>(ITreeChildren<T> t) where T : ITreeChildren<T>
  106. {
  107. return t.Children.Union(t.Children.Where(c => c.Children.Any()).SelectMany(tree => GetChildren(tree))).ToList();
  108. }
  109. /// <summary>
  110. /// 递归取出所有上级
  111. /// </summary>
  112. /// <param name="t"></param>
  113. /// <returns></returns>
  114. private static List<T> GetParents<T>(ITreeParent<T> t) where T : ITreeParent<T>
  115. {
  116. var list = new List<T>() { t.Parent };
  117. return t.Parent != null ? list.Union(GetParents(t.Parent)).ToList() : list;
  118. }
  119. }
  120. }