code_junkie

Recursive List Flattening

Nov 11th, 2011
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.32 KB | None | 0 0
  1. public static IEnumerable<TElement> Flatten<TElement,TSequence> (this IEnumerable<TSequence> sequences)
  2. where TSequence : IEnumerable<TElement>
  3. {
  4. foreach (TSequence sequence in sequences)
  5. {
  6. foreach(TElement element in sequence)
  7. {
  8. yield return element;
  9. }
  10. }
  11. }
  12.  
  13. static IEnumerable Flatten(params object[] objects)
  14. {
  15. // Can't easily get varargs behaviour with IEnumerable
  16. return Flatten((IEnumerable) objects);
  17. }
  18.  
  19. static IEnumerable Flatten(IEnumerable enumerable)
  20. {
  21. foreach (object element in enumerable)
  22. {
  23. IEnumerable candidate = element as IEnumerable;
  24. if (candidate != null)
  25. {
  26. foreach (object nested in candidate)
  27. {
  28. yield return nested;
  29. }
  30. }
  31. else
  32. {
  33. yield return element;
  34. }
  35. }
  36. }
  37.  
  38. /// Traverses an object hierarchy and return a flattened list of elements
  39. /// based on a predicate.
  40. ///
  41. /// TSource: The type of object in your collection.</typeparam>
  42. /// source: The collection of your topmost TSource objects.</param>
  43. /// selectorFunction: A predicate for choosing the objects you want.
  44. /// getChildrenFunction: A function that fetches the child collection from an object.
  45. /// returns: A flattened list of objects which meet the criteria in selectorFunction.
  46. public static IEnumerable<TSource> Map<TSource>(
  47. this IEnumerable<TSource> source,
  48. Func<TSource, bool> selectorFunction,
  49. Func<TSource, IEnumerable<TSource>> getChildrenFunction)
  50. {
  51. // Add what we have to the stack
  52. var flattenedList = source.Where(selectorFunction);
  53.  
  54. // Go through the input enumerable looking for children,
  55. // and add those if we have them
  56. foreach (TSource element in source)
  57. {
  58. flattenedList = flattenedList.Concat(
  59. getChildrenFunction(element).Map(selectorFunction,
  60. getChildrenFunction)
  61. );
  62. }
  63. return flattenedList;
  64. }
  65.  
  66. class Node
  67. {
  68. public int NodeId { get; set; }
  69. public int LevelId { get; set; }
  70. public IEnumerable<Node> Children { get; set; }
  71.  
  72. public override string ToString()
  73. {
  74. return String.Format("Node {0}, Level {1}", this.NodeId, this.LevelId);
  75. }
  76. }
  77.  
  78. private IEnumerable<Node> GetNodes()
  79. {
  80. // Create a 3-level deep hierarchy of nodes
  81. Node[] nodes = new Node[]
  82. {
  83. new Node
  84. {
  85. NodeId = 1,
  86. LevelId = 1,
  87. Children = new Node[]
  88. {
  89. new Node { NodeId = 2, LevelId = 2, Children = new Node[] {} },
  90. new Node
  91. {
  92. NodeId = 3,
  93. LevelId = 2,
  94. Children = new Node[]
  95. {
  96. new Node { NodeId = 4, LevelId = 3, Children = new Node[] {} },
  97. new Node { NodeId = 5, LevelId = 3, Children = new Node[] {} }
  98. }
  99. }
  100. }
  101. },
  102. new Node { NodeId = 6, LevelId = 1, Children = new Node[] {} }
  103. };
  104. return nodes;
  105. }
  106.  
  107. [Test]
  108. public void Flatten_Nested_Heirachy()
  109. {
  110. IEnumerable<Node> nodes = GetNodes();
  111. var flattenedNodes = nodes.Map(
  112. p => true,
  113. (Node n) => { return n.Children; }
  114. );
  115. foreach (Node flatNode in flattenedNodes)
  116. {
  117. Console.WriteLine(flatNode.ToString());
  118. }
  119.  
  120. // Make sure we only end up with 6 nodes
  121. Assert.AreEqual(6, flattenedNodes.Count());
  122. }
  123.  
  124. [Test]
  125. public void Only_Return_Nodes_With_Even_Numbered_Node_IDs()
  126. {
  127. IEnumerable<Node> nodes = GetNodes();
  128. var flattenedNodes = nodes.Map(
  129. p => (p.NodeId % 2) == 0,
  130. (Node n) => { return n.Children; }
  131. );
  132. foreach (Node flatNode in flattenedNodes)
  133. {
  134. Console.WriteLine(flatNode.ToString());
  135. }
  136. // Make sure we only end up with 3 nodes
  137. Assert.AreEqual(3, flattenedNodes.Count());
  138. }
  139.  
  140. Node 6, Level 1
  141. Node 2, Level 2
  142. Node 4, Level 3
  143.  
  144. enum1.SelectMany(
  145. a => a.SelectMany(
  146. b => b.SelectMany(
  147. c => c.Select(
  148. d => d.Name
  149. )
  150. )
  151. )
  152. );
  153.  
  154. static IEnumerable Flatten(IEnumerable enumerable)
  155. {
  156. foreach (object element in enumerable)
  157. {
  158. IEnumerable candidate = element as IEnumerable;
  159. if (candidate != null)
  160. {
  161. foreach (object nested in Flatten(candidate))
  162. {
  163. yield return nested;
  164. }
  165. }
  166. else
  167. {
  168. yield return element;
  169. }
  170. }
  171. }
  172.  
  173. #!/usr/bin/env python
  174.  
  175. def flatten(iterable):
  176. for item in iterable:
  177. if hasattr(item, '__iter__'):
  178. for nested in flatten(item):
  179. yield nested
  180. else:
  181. yield item
  182.  
  183. if __name__ == '__main__':
  184. for item in flatten([1,[2, 3, [[4], 5]], 6, [[[7]]], [8]]):
  185. print(item, end=" ")
  186.  
  187. 1 2 3 4 5 6 7 8
  188.  
  189. static class EnumerableExtensions
  190. {
  191. public static IEnumerable<T> Flatten<T>(this IEnumerable<IEnumerable<T>> sequence)
  192. {
  193. foreach(var child in sequence)
  194. foreach(var item in child)
  195. yield return item;
  196. }
  197. }
  198.  
  199. <Extension()>
  200. Public Function Flatten(Of T)(ByVal objects As Generic.IEnumerable(Of T), ByVal selector As Func(Of T, Generic.IEnumerable(Of T))) As Generic.IEnumerable(Of T)
  201. Return objects.Union(objects.SelectMany(selector).Flatten(selector))
  202. End Function
  203.  
  204. private void flattenList(IEnumerable<T> list)
  205. {
  206. foreach (T item in list)
  207. {
  208. masterList.Add(item);
  209.  
  210. if (item.Count > 0)
  211. {
  212. this.flattenList(item);
  213. }
  214. }
  215. }
Add Comment
Please, Sign In to add comment