Implementing some useful Enumerable Extension methods from Ruby
I don’t know much about Ruby, but I am huge fan of PrototypeJS and therefore I decided to implement some of the Enumerable methods that are found within that framework (which actually comes from Ruby).
I have made two extension classes; one is called EnumerableExtension and the other ArrayExtension. I have submitted the enum extension to the MvcContrib Project, but for some reason it seems like I have forgotten the array extension, so it might get submitted later on.
The PrototypeJS Api has some great examples on how these methods work, so if you want to learn more about them, then you should check that out.
I hope that you will find them useful.
The Enumerable Extensions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | public static class EnumerableExtension { /// <summary> /// Returns all the elements that match the filter. /// </summary> /// <typeparam name="TEnumerable"></typeparam> /// <param name="enumerable"></param> /// <param name="filter"></param> /// <returns></returns> public static IEnumerable<TEnumerable> GRep<TEnumerable>(this IEnumerable<TEnumerable> enumerable, string filter) { var regex = new Regex(filter); foreach (TEnumerable item in enumerable) { if (regex.IsMatch(item.ToString())) { yield return (item); } } } /// <summary> /// Returns the results of applying the iterator to each element. /// </summary> /// <typeparam name="TEnumerable"></typeparam> /// <typeparam name="T2"></typeparam> /// <param name="enumerable"></param> /// <param name="func"></param> /// <returns></returns> public static IEnumerable<T2> Map<TEnumerable, T2>(this IEnumerable<TEnumerable> enumerable, Func<TEnumerable, T2> func) { foreach (TEnumerable item in enumerable) { yield return func(item); } } /// <summary> /// Returns all the elements for which the iterator returned false. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="enumerable"></param> /// <param name="match"></param> /// <returns></returns> public static IEnumerable<T> Reject<T>(this IEnumerable<T> enumerable, Predicate<T> match) { foreach (T item in enumerable) { if (!match(item)) { yield return item; } } } /// <summary> /// Incrementally builds a result value based on the successive results of the iterator. This can be used for array construction, numerical sums/averages, etc. /// </summary> /// <typeparam name="TEnumerable"></typeparam> /// <typeparam name="TMemo"></typeparam> /// <param name="enumerable"></param> /// <param name="accumulator"></param> /// <param name="func"></param> /// <returns></returns> public static TMemo Inject<TEnumerable, TMemo>(this IEnumerable<TEnumerable> enumerable, TMemo accumulator, Func<TMemo, TEnumerable, TMemo> func) { enumerable.Each(item => accumulator = func(accumulator, item)); return accumulator; } /// <summary> /// Incrementally builds a result value based on the successive results of the iterator. This can be used for array construction, numerical sums/averages, etc. /// </summary> /// <typeparam name="TEnumerable"></typeparam> /// <typeparam name="TMemo"></typeparam> /// <param name="enumerable"></param> /// <param name="accumulator"></param> /// <param name="func"></param> /// <returns></returns> public static TMemo Inject<TEnumerable, TMemo>(this IEnumerable<TEnumerable> enumerable, TMemo accumulator, Func<TMemo, TEnumerable, int, TMemo> func) { enumerable.Each((item, index) => accumulator = func(accumulator, item, index)); return accumulator; } /// <summary> /// It lets you iterate over all the elements in a generic fashion, then returns the Enumerable, thereby allowing chain-calling. /// </summary> /// <typeparam name="TEnumerable"></typeparam> /// <param name="enumerable"></param> /// <param name="iterator"></param> public static void Each<TEnumerable>(this IEnumerable<TEnumerable> enumerable, Action<TEnumerable> iterator) { for(var i = 0; i < enumerable.Count(); i++) { iterator(enumerable.ToArray()[i]); } } /// <summary> /// It lets you iterate over all the elements in a generic fashion, then returns the Enumerable, thereby allowing chain-calling. /// </summary> /// <typeparam name="TEnumerable"></typeparam> /// <param name="enumerable"></param> /// <param name="iterator"></param> public static void Each<TEnumerable>(this IEnumerable<TEnumerable> enumerable, Action<TEnumerable, int> iterator) { for (var index = 0; index < enumerable.Count(); index++) { iterator(enumerable.ToArray()[index], index); } } public static string ToJSON<T>(this IEnumerable<T> enumerable) { var serializer = new JavaScriptSerializer(); return serializer.Serialize(enumerable); } } |
The Array Extension
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public static class ArrayExtension { /// <summary> /// Produces a new version of the array that does not contain any of the specified values. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="array"></param> /// <param name="values"></param> /// <returns></returns> public static T[] Without<T>(this T[] array, params T[] values) { return array.Reject(t => values.Contains(t)).ToArray(); } } |
Further Reading