EnumerableOperations.vala 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  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. // Root handler
  11. class RootEndpoint : Object, Endpoint {
  12. public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
  13. return new HttpStringResult("""Enumerable Operations Demo
  14. This example demonstrates various LINQ-like operations available in Invercargill Enumerable:
  15. Endpoints:
  16. GET /filter - Filtering examples
  17. GET /map - Mapping/Projection examples
  18. GET /group-by - Grouping examples
  19. GET /aggregate - Aggregation examples
  20. GET /sort - Sorting examples
  21. GET /set-operations - Set operations (union, intersection, etc.)
  22. GET /advanced - Advanced operations (zip, partition, etc.)
  23. """);
  24. }
  25. }
  26. // Filtering examples
  27. class FilterEndpoint : Object, Endpoint {
  28. public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
  29. var numbers = Wrap.array<int>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
  30. var parts = new Series<string>();
  31. parts.add_start("Original: ");
  32. parts.add_start(enumerable_int_to_string(numbers.as_enumerable()));
  33. parts.add_start("\n\n");
  34. // Filter even numbers
  35. var even = numbers.as_enumerable()
  36. .where(n => n % 2 == 0);
  37. parts.add_start("Even numbers: ");
  38. parts.add_start(enumerable_int_to_string(even));
  39. parts.add_start("\n");
  40. // Filter odd numbers
  41. var odd = numbers.as_enumerable()
  42. .where(n => n % 2 != 0);
  43. parts.add_start("Odd numbers: ");
  44. parts.add_start(enumerable_int_to_string(odd));
  45. parts.add_start("\n");
  46. // Filter numbers greater than 5
  47. var greater_than_5 = numbers.as_enumerable()
  48. .where(n => n > 5);
  49. parts.add_start("Greater than 5: ");
  50. parts.add_start(enumerable_int_to_string(greater_than_5));
  51. parts.add_start("\n\n");
  52. // Chained filters
  53. var filtered = numbers.as_enumerable()
  54. .where(n => n > 3)
  55. .where(n => n < 8);
  56. parts.add_start("Between 3 and 8: ");
  57. parts.add_start(enumerable_int_to_string(filtered));
  58. var result = parts.to_immutable_buffer()
  59. .aggregate<string>("", (acc, s) => acc + s);
  60. return new HttpStringResult(result);
  61. }
  62. }
  63. // Mapping/Projection examples
  64. class MapEndpoint : Object, Endpoint {
  65. public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
  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 HttpStringResult(result);
  98. }
  99. }
  100. // Grouping examples
  101. class GroupByEndpoint : Object, Endpoint {
  102. public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
  103. var words = Wrap.array<string>({
  104. "apple", "banana", "cherry", "apricot",
  105. "blueberry", "blackberry", "coconut"
  106. });
  107. var parts = new Series<string>();
  108. parts.add_start("Words: ");
  109. parts.add_start(enumerable_string_to_string(words.as_enumerable()));
  110. parts.add_start("\n\n");
  111. // Group by first letter
  112. var grouped = words.as_enumerable()
  113. .group_by<string>(w => w.get_char(0).to_string());
  114. parts.add_start("Grouped by first letter:\n");
  115. grouped.iterate((grouping) => {
  116. parts.add_start(@" $(grouping.key): ");
  117. parts.add_start(enumerable_string_to_string(grouping.to_immutable_buffer()));
  118. parts.add_start("\n");
  119. });
  120. var result = parts.to_immutable_buffer()
  121. .aggregate<string>("", (acc, s) => acc + s);
  122. return new HttpStringResult(result);
  123. }
  124. }
  125. // Aggregation examples
  126. class AggregateEndpoint : Object, Endpoint {
  127. public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
  128. var numbers = Wrap.array<int>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
  129. var parts = new Series<string>();
  130. parts.add_start("Numbers: ");
  131. parts.add_start(enumerable_int_to_string(numbers.as_enumerable()));
  132. parts.add_start("\n\n");
  133. // Count
  134. var count = numbers.as_enumerable().count();
  135. parts.add_start(@"Count: $count\n");
  136. // Sum using aggregate
  137. var sum = numbers.as_enumerable()
  138. .aggregate<int>(0, (acc, n) => acc + n);
  139. parts.add_start(@"Sum: $sum\n");
  140. // Average
  141. var avg = (double)sum / count;
  142. parts.add_start(@"Average: $avg\n");
  143. // Min
  144. var min = numbers.as_enumerable().min(n => n);
  145. parts.add_start(@"Min: $min\n");
  146. // Max
  147. var max = numbers.as_enumerable().max(n => n);
  148. parts.add_start(@"Max: $max\n");
  149. // First
  150. var first = numbers.as_enumerable().first();
  151. parts.add_start(@"First: $first\n");
  152. // Last
  153. var last = numbers.as_enumerable().last();
  154. parts.add_start(@"Last: $last\n");
  155. var result = parts.to_immutable_buffer()
  156. .aggregate<string>("", (acc, s) => acc + s);
  157. return new HttpStringResult(result);
  158. }
  159. }
  160. // Sorting examples
  161. class SortEndpoint : Object, Endpoint {
  162. public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
  163. var numbers = Wrap.array<int>({5, 2, 8, 1, 9, 3, 7, 4, 6, 10});
  164. var parts = new Series<string>();
  165. parts.add_start("Original: ");
  166. parts.add_start(enumerable_int_to_string(numbers.as_enumerable()));
  167. parts.add_start("\n\n");
  168. // Sort ascending
  169. var sorted_asc = numbers.as_enumerable()
  170. .order_by<int>(n => n);
  171. parts.add_start("Ascending: ");
  172. parts.add_start(enumerable_int_to_string(sorted_asc));
  173. parts.add_start("\n");
  174. // Sort descending
  175. var sorted_desc = numbers.as_enumerable()
  176. .order_by_descending<int>(n => n);
  177. parts.add_start("Descending: ");
  178. parts.add_start(enumerable_int_to_string(sorted_desc));
  179. var result = parts.to_immutable_buffer()
  180. .aggregate<string>("", (acc, s) => acc + s);
  181. return new HttpStringResult(result);
  182. }
  183. }
  184. // Set operations
  185. class SetOperationsEndpoint : Object, Endpoint {
  186. public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
  187. var set1 = Wrap.array<int>({1, 2, 3, 4, 5});
  188. var set2 = Wrap.array<int>({4, 5, 6, 7, 8});
  189. var parts = new Series<string>();
  190. parts.add_start("Set 1: ");
  191. parts.add_start(enumerable_int_to_string(set1.as_enumerable()));
  192. parts.add_start("\n");
  193. parts.add_start("Set 2: ");
  194. parts.add_start(enumerable_int_to_string(set2.as_enumerable()));
  195. parts.add_start("\n\n");
  196. // Union (concat)
  197. var union = set1.as_enumerable().concat(set2.as_enumerable());
  198. parts.add_start("Union: ");
  199. parts.add_start(enumerable_int_to_string(union));
  200. parts.add_start("\n");
  201. // Common (intersection)
  202. var common = set1.as_enumerable().common(set2.as_enumerable());
  203. parts.add_start("Common: ");
  204. parts.add_start(enumerable_int_to_string(common));
  205. parts.add_start("\n");
  206. // Non-common (difference)
  207. var diff = set1.as_enumerable().non_common(set2.as_enumerable());
  208. parts.add_start("In set1 but not set2: ");
  209. parts.add_start(enumerable_int_to_string(diff));
  210. var result = parts.to_immutable_buffer()
  211. .aggregate<string>("", (acc, s) => acc + s);
  212. return new HttpStringResult(result);
  213. }
  214. }
  215. // Advanced operations
  216. class AdvancedEndpoint : Object, Endpoint {
  217. public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
  218. var numbers = Wrap.array<int>({1, 2, 3, 4, 5});
  219. var parts = new Series<string>();
  220. // Take
  221. var taken = numbers.as_enumerable().take(3);
  222. parts.add_start("Take 3: ");
  223. parts.add_start(enumerable_int_to_string(taken));
  224. parts.add_start("\n");
  225. // Skip
  226. var skipped = numbers.as_enumerable().skip(2);
  227. parts.add_start("Skip 2: ");
  228. parts.add_start(enumerable_int_to_string(skipped));
  229. parts.add_start("\n");
  230. // Distinct
  231. var with_dupes = Wrap.array<int>({1, 2, 2, 3, 3, 3, 4});
  232. var distinct = with_dupes.as_enumerable().distinct();
  233. parts.add_start("Distinct from {1,2,2,3,3,3,4}: ");
  234. parts.add_start(enumerable_int_to_string(distinct));
  235. parts.add_start("\n");
  236. // Reverse
  237. var reversed = numbers.as_enumerable().reverse();
  238. parts.add_start("Reversed: ");
  239. parts.add_start(enumerable_int_to_string(reversed));
  240. var result = parts.to_immutable_buffer()
  241. .aggregate<string>("", (acc, s) => acc + s);
  242. return new HttpStringResult(result);
  243. }
  244. }
  245. void main() {
  246. var application = new WebApplication(8087);
  247. application.container.register_scoped<Endpoint>(() => new RootEndpoint())
  248. .with_metadata<EndpointRoute>(new EndpointRoute("/"));
  249. application.container.register_scoped<Endpoint>(() => new FilterEndpoint())
  250. .with_metadata<EndpointRoute>(new EndpointRoute("/filter"));
  251. application.container.register_scoped<Endpoint>(() => new MapEndpoint())
  252. .with_metadata<EndpointRoute>(new EndpointRoute("/map"));
  253. application.container.register_scoped<Endpoint>(() => new GroupByEndpoint())
  254. .with_metadata<EndpointRoute>(new EndpointRoute("/group-by"));
  255. application.container.register_scoped<Endpoint>(() => new AggregateEndpoint())
  256. .with_metadata<EndpointRoute>(new EndpointRoute("/aggregate"));
  257. application.container.register_scoped<Endpoint>(() => new SortEndpoint())
  258. .with_metadata<EndpointRoute>(new EndpointRoute("/sort"));
  259. application.container.register_scoped<Endpoint>(() => new SetOperationsEndpoint())
  260. .with_metadata<EndpointRoute>(new EndpointRoute("/set-operations"));
  261. application.container.register_scoped<Endpoint>(() => new AdvancedEndpoint())
  262. .with_metadata<EndpointRoute>(new EndpointRoute("/advanced"));
  263. print("Enumerable Operations Demo Server running on port 8087\n");
  264. print("Try these endpoints:\n");
  265. print(" - http://localhost:8087/\n");
  266. print(" - http://localhost:8087/filter\n");
  267. print(" - http://localhost:8087/map\n");
  268. print(" - http://localhost:8087/group-by\n");
  269. print(" - http://localhost:8087/aggregate\n");
  270. print(" - http://localhost:8087/sort\n");
  271. print(" - http://localhost:8087/set-operations\n");
  272. print(" - http://localhost:8087/advanced\n");
  273. application.run();
  274. }
  275. // Helper functions
  276. string enumerable_int_to_string(Enumerable<int> enumerable) {
  277. return enumerable.to_immutable_buffer()
  278. .aggregate<string>("[", (acc, n) => {
  279. if (acc == "[") return acc + n.to_string();
  280. return acc + ", " + n.to_string();
  281. }) + "]";
  282. }
  283. string enumerable_string_to_string(Enumerable<string> enumerable) {
  284. return enumerable.to_immutable_buffer()
  285. .aggregate<string>("[", (acc, s) => {
  286. if (acc == "[") return acc + "\"" + s + "\"";
  287. return acc + ", \"" + s + "\"";
  288. }) + "]";
  289. }