fork download
  1. using System;
  2. using System.Linq;
  3. using System.Collections.Generic;
  4.  
  5. public static class MyExtensions
  6. {
  7. public static IEnumerable<T> Traverse<T>(
  8. this IEnumerable<T> source,
  9. Func<T, IEnumerable<T>> fnRecurse)
  10. {
  11. if (source != null)
  12. {
  13. Stack<IEnumerator<T>> enumerators = new Stack<IEnumerator<T>>();
  14. try
  15. {
  16. enumerators.Push(source.GetEnumerator());
  17. while (enumerators.Count > 0)
  18. {
  19. var top = enumerators.Peek();
  20. while (top.MoveNext())
  21. {
  22. yield return top.Current;
  23.  
  24. var children = fnRecurse(top.Current);
  25. if (children != null)
  26. {
  27. top = children.GetEnumerator();
  28. enumerators.Push(top);
  29. }
  30. }
  31.  
  32. enumerators.Pop().Dispose();
  33. }
  34. }
  35. finally
  36. {
  37. while (enumerators.Count > 0)
  38. enumerators.Pop().Dispose();
  39. }
  40. }
  41. }
  42.  
  43. public static IEnumerable<(T, int[])> Expand<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> getChildren) {
  44. var stack = new Stack<IEnumerator<T>>();
  45. var e = source.GetEnumerator();
  46. List<int> indexes = new List<int>() { -1 };
  47. try {
  48. while (true) {
  49. while (e.MoveNext()) {
  50. var item = e.Current;
  51. indexes[stack.Count]++;
  52. yield return (item, indexes.Take(stack.Count + 1).ToArray());
  53. var elements = getChildren(item);
  54. if (elements == null) continue;
  55. stack.Push(e);
  56. e = elements.GetEnumerator();
  57. if (indexes.Count == stack.Count)
  58. indexes.Add(-1);
  59. }
  60. if (stack.Count == 0) break;
  61. e.Dispose();
  62. indexes[stack.Count] = -1;
  63. e = stack.Pop();
  64. }
  65. } finally {
  66. e.Dispose();
  67. while (stack.Count != 0) stack.Pop().Dispose();
  68. }
  69. }
  70. }
  71.  
  72. public class Node
  73. {
  74. public int Id;
  75. public List<Node> Children;
  76. }
  77.  
  78. public class Test
  79. {
  80. public static void Main()
  81. {
  82. List<Node> nodes = new List<Node>()
  83. {
  84. new Node()
  85. {
  86. Id = 1,
  87. Children = new List<Node>()
  88. {
  89. new Node()
  90. {
  91. Id = 2,
  92. Children = new List<Node>()
  93. {
  94. new Node()
  95. {
  96. Id = 4
  97. },
  98. new Node()
  99. {
  100. Id = 5
  101. }
  102. }
  103. },
  104. new Node()
  105. {
  106. Id = 3
  107. }
  108. }
  109. }
  110. };
  111.  
  112. Console.WriteLine(String.Join(", ", nodes.Traverse(n => n.Children).Select(n => n.Id)));
  113. Console.WriteLine(String.Join(", ", nodes.Expand(n => n.Children).Select(n => $"{n.Item1.Id}: { String.Join(", ", n.Item2)}")));
  114. }
  115. }
Success #stdin #stdout 0.03s 29372KB
stdin
Standard input is empty
stdout
1, 2, 4, 5, 3
1: 0, 2: 0, 0, 4: 0, 0, 0, 5: 0, 0, 1, 3: 0, 1