EnumerableOperations.vala 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. using Astralis;
  2. using Invercargill;
  3. using Invercargill.DataStructures;
  4. /**
  5. * EnumerableOperations Example
  6. *
  7. * Demonstrates various LINQ-like operations available in Invercargill Enumerable.
  8. * This example shows filtering, mapping, grouping, and aggregation operations.
  9. */
  10. void main() {
  11. var router = new Router();
  12. var server = new Server(8087, router);
  13. // Root endpoint
  14. router.map_func("/", (context) => {
  15. return new BufferedHttpResult.from_string(
  16. """Enumerable Operations Demo
  17. This example demonstrates various LINQ-like operations available in Invercargill Enumerable:
  18. Endpoints:
  19. GET /filter - Filtering examples
  20. GET /map - Mapping/Projection examples
  21. GET /group-by - Grouping examples
  22. GET /aggregate - Aggregation examples
  23. GET /sort - Sorting examples
  24. GET /set-operations - Set operations (union, intersection, etc.)
  25. GET /advanced - Advanced operations (zip, partition, etc.)
  26. """
  27. );
  28. });
  29. // Filtering examples
  30. router.map_func("/filter", (context) => {
  31. var numbers = Wrap.array<int>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
  32. var parts = new Series<string>();
  33. parts.add_start("Original: ");
  34. parts.add_start(enumerable_int_to_string(numbers.as_enumerable()));
  35. parts.add_start("\n\n");
  36. // Filter even numbers
  37. var even = numbers.as_enumerable()
  38. .where(n => n % 2 == 0);
  39. parts.add_start("Even numbers: ");
  40. parts.add_start(enumerable_int_to_string(even));
  41. parts.add_start("\n");
  42. // Filter odd numbers
  43. var odd = numbers.as_enumerable()
  44. .where(n => n % 2 != 0);
  45. parts.add_start("Odd numbers: ");
  46. parts.add_start(enumerable_int_to_string(odd));
  47. parts.add_start("\n");
  48. // Filter numbers greater than 5
  49. var greater_than_5 = numbers.as_enumerable()
  50. .where(n => n > 5);
  51. parts.add_start("Greater than 5: ");
  52. parts.add_start(enumerable_int_to_string(greater_than_5));
  53. parts.add_start("\n\n");
  54. // Chained filters
  55. var filtered = numbers.as_enumerable()
  56. .where(n => n > 3)
  57. .where(n => n < 8);
  58. parts.add_start("Between 3 and 8: ");
  59. parts.add_start(enumerable_int_to_string(filtered));
  60. var result = parts.to_immutable_buffer()
  61. .aggregate<string>("", (acc, s) => acc + s);
  62. return new BufferedHttpResult.from_string(result);
  63. });
  64. // Mapping/Projection examples
  65. router.map_func("/map", (context) => {
  66. var numbers = Wrap.array<int>({1, 2, 3, 4, 5});
  67. var parts = new Series<string>();
  68. parts.add_start("Original: ");
  69. parts.add_start(enumerable_int_to_string(numbers.as_enumerable()));
  70. parts.add_start("\n\n");
  71. // Square each number
  72. var squared = numbers.as_enumerable()
  73. .select<int>(n => n * n);
  74. parts.add_start("Squared: ");
  75. parts.add_start(enumerable_int_to_string(squared));
  76. parts.add_start("\n");
  77. // Double each number
  78. var doubled = numbers.as_enumerable()
  79. .select<int>(n => n * 2);
  80. parts.add_start("Doubled: ");
  81. parts.add_start(enumerable_int_to_string(doubled));
  82. parts.add_start("\n");
  83. // Convert to string
  84. var as_strings = numbers.as_enumerable()
  85. .select<string>(n => n.to_string());
  86. parts.add_start("As strings: ");
  87. parts.add_start(enumerable_string_to_string(as_strings));
  88. parts.add_start("\n\n");
  89. // With index
  90. var with_index = numbers.as_enumerable()
  91. .with_positions()
  92. .select<string>(pair => @"$(pair.item) at index $(pair.position)");
  93. parts.add_start("With index: ");
  94. parts.add_start(enumerable_string_to_string(with_index));
  95. var result = parts.to_immutable_buffer()
  96. .aggregate<string>("", (acc, s) => acc + s);
  97. return new BufferedHttpResult.from_string(result);
  98. });
  99. // Grouping examples
  100. router.map_func("/group-by", (context) => {
  101. var words = Wrap.array<string>({
  102. "apple", "banana", "cherry", "apricot",
  103. "blueberry", "blackberry", "coconut"
  104. });
  105. var parts = new Series<string>();
  106. parts.add_start("Words: ");
  107. parts.add_start(enumerable_string_to_string(words.as_enumerable()));
  108. parts.add_start("\n\n");
  109. // Group by first letter
  110. var grouped = words.as_enumerable()
  111. .group_by<string>(w => w.get_char(0).to_string());
  112. parts.add_start("Grouped by first letter:\n");
  113. grouped.iterate((grouping) => {
  114. parts.add_start(@" $(grouping.key): ");
  115. parts.add_start(enumerable_string_to_string(grouping.to_immutable_buffer()));
  116. parts.add_start("\n");
  117. });
  118. var result = parts.to_immutable_buffer()
  119. .aggregate<string>("", (acc, s) => acc + s);
  120. return new BufferedHttpResult.from_string(result);
  121. });
  122. // Aggregation examples
  123. router.map_func("/aggregate", (context) => {
  124. var numbers = Wrap.array<int>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
  125. var parts = new Series<string>();
  126. parts.add_start("Numbers: ");
  127. parts.add_start(enumerable_int_to_string(numbers.as_enumerable()));
  128. parts.add_start("\n\n");
  129. // Count
  130. var count = numbers.as_enumerable().count();
  131. parts.add_start(@"Count: $count\n");
  132. // Sum using aggregate
  133. var sum = numbers.as_enumerable()
  134. .aggregate<int>(0, (acc, n) => acc + n);
  135. parts.add_start(@"Sum: $sum\n");
  136. // Average
  137. var avg = (double)sum / count;
  138. parts.add_start(@"Average: $avg\n");
  139. // Min
  140. var min = numbers.as_enumerable().min(n => n);
  141. parts.add_start(@"Min: $min\n");
  142. // Max
  143. var max = numbers.as_enumerable().max(n => n);
  144. parts.add_start(@"Max: $max\n");
  145. // First
  146. var first = numbers.as_enumerable().first();
  147. parts.add_start(@"First: $first\n");
  148. // Last
  149. var last = numbers.as_enumerable().last();
  150. parts.add_start(@"Last: $last\n");
  151. var result = parts.to_immutable_buffer()
  152. .aggregate<string>("", (acc, s) => acc + s);
  153. return new BufferedHttpResult.from_string(result);
  154. });
  155. // Sorting examples
  156. router.map_func("/sort", (context) => {
  157. var numbers = Wrap.array<int>({5, 2, 8, 1, 9, 3, 7, 4, 6, 10});
  158. var parts = new Series<string>();
  159. parts.add_start("Original: ");
  160. parts.add_start(enumerable_int_to_string(numbers.as_enumerable()));
  161. parts.add_start("\n\n");
  162. // Sort ascending
  163. var sorted_asc = numbers.as_enumerable()
  164. .order_by<int>(n => n);
  165. parts.add_start("Ascending: ");
  166. parts.add_start(enumerable_int_to_string(sorted_asc));
  167. parts.add_start("\n");
  168. // Sort descending
  169. var sorted_desc = numbers.as_enumerable()
  170. .order_by_descending<int>(n => n);
  171. parts.add_start("Descending: ");
  172. parts.add_start(enumerable_int_to_string(sorted_desc));
  173. var result = parts.to_immutable_buffer()
  174. .aggregate<string>("", (acc, s) => acc + s);
  175. return new BufferedHttpResult.from_string(result);
  176. });
  177. // Set operations
  178. router.map_func("/set-operations", (context) => {
  179. var set1 = Wrap.array<int>({1, 2, 3, 4, 5});
  180. var set2 = Wrap.array<int>({4, 5, 6, 7, 8});
  181. var parts = new Series<string>();
  182. parts.add_start("Set 1: ");
  183. parts.add_start(enumerable_int_to_string(set1.as_enumerable()));
  184. parts.add_start("\n");
  185. parts.add_start("Set 2: ");
  186. parts.add_start(enumerable_int_to_string(set2.as_enumerable()));
  187. parts.add_start("\n\n");
  188. // Union (concat)
  189. var union = set1.as_enumerable().concat(set2.as_enumerable());
  190. parts.add_start("Union: ");
  191. parts.add_start(enumerable_int_to_string(union));
  192. parts.add_start("\n");
  193. // Common (intersection)
  194. var common = set1.as_enumerable().common(set2.as_enumerable());
  195. parts.add_start("Common: ");
  196. parts.add_start(enumerable_int_to_string(common));
  197. parts.add_start("\n");
  198. // Non-common (difference)
  199. var diff = set1.as_enumerable().non_common(set2.as_enumerable());
  200. parts.add_start("In set1 but not set2: ");
  201. parts.add_start(enumerable_int_to_string(diff));
  202. var result = parts.to_immutable_buffer()
  203. .aggregate<string>("", (acc, s) => acc + s);
  204. return new BufferedHttpResult.from_string(result);
  205. });
  206. // Advanced operations
  207. router.map_func("/advanced", (context) => {
  208. var numbers = Wrap.array<int>({1, 2, 3, 4, 5});
  209. var parts = new Series<string>();
  210. // Take
  211. var taken = numbers.as_enumerable().take(3);
  212. parts.add_start("Take 3: ");
  213. parts.add_start(enumerable_int_to_string(taken));
  214. parts.add_start("\n");
  215. // Skip
  216. var skipped = numbers.as_enumerable().skip(2);
  217. parts.add_start("Skip 2: ");
  218. parts.add_start(enumerable_int_to_string(skipped));
  219. parts.add_start("\n");
  220. // Distinct
  221. var with_dupes = Wrap.array<int>({1, 2, 2, 3, 3, 3, 4});
  222. var distinct = with_dupes.as_enumerable().distinct();
  223. parts.add_start("Distinct from {1,2,2,3,3,3,4}: ");
  224. parts.add_start(enumerable_int_to_string(distinct));
  225. parts.add_start("\n");
  226. // Reverse
  227. var reversed = numbers.as_enumerable().reverse();
  228. parts.add_start("Reversed: ");
  229. parts.add_start(enumerable_int_to_string(reversed));
  230. var result = parts.to_immutable_buffer()
  231. .aggregate<string>("", (acc, s) => acc + s);
  232. return new BufferedHttpResult.from_string(result);
  233. });
  234. print("Enumerable Operations Demo Server running on port 8087\n");
  235. print("Try these endpoints:\n");
  236. print(" - http://localhost:8087/\n");
  237. print(" - http://localhost:8087/filter\n");
  238. print(" - http://localhost:8087/map\n");
  239. print(" - http://localhost:8087/group-by\n");
  240. print(" - http://localhost:8087/aggregate\n");
  241. print(" - http://localhost:8087/sort\n");
  242. print(" - http://localhost:8087/set-operations\n");
  243. print(" - http://localhost:8087/advanced\n");
  244. server.run();
  245. }
  246. // Helper functions
  247. string enumerable_int_to_string(Enumerable<int> enumerable) {
  248. return enumerable.to_immutable_buffer()
  249. .aggregate<string>("[", (acc, n) => {
  250. if (acc == "[") return acc + n.to_string();
  251. return acc + ", " + n.to_string();
  252. }) + "]";
  253. }
  254. string enumerable_string_to_string(Enumerable<string> enumerable) {
  255. return enumerable.to_immutable_buffer()
  256. .aggregate<string>("[", (acc, s) => {
  257. if (acc == "[") return acc + "\"" + s + "\"";
  258. return acc + ", \"" + s + "\"";
  259. }) + "]";
  260. }