Given a range (start,end) and a number of steps, will yield that a number for each step
//http://isotopescreencapture.codeplex.com/ //The MIT License (MIT) using System.Collections.Generic; using System.Linq; namespace Isotope.Collections { public static partial class EnumerableUtil { public static IEnumerable<T> Single<T>(T item) { yield return item; } /// <summary> /// Given a range (start,end) and a number of steps, will yield that a number for each step /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <param name="steps"></param> /// <returns></returns> public static IEnumerable<double> RangeSteps(double start, double end, int steps) { // for non-positive number of steps, yield no points if (steps < 1) { yield break; } // for exactly 1 step, yield the start value if (steps == 1) { yield return start; yield break; } // for exactly 2 stesp, yield the start value, and then the end value if (steps == 2) { yield return start; yield return end; yield break; } // for 3 steps or above, start yielding the segments // notice that the start and end values are explicitly returned so that there // is no possibility of rounding error affecting their values int segments = steps - 1; double total_length = end - start; double stepsize = total_length / segments; yield return start; for (int i = 1; i < (steps-1); i++) { double p = start + (stepsize*i); yield return p; } yield return end; } public static IEnumerable<TGROUP> GroupByCount<T, TGROUP>( IEnumerable<T> items, int group_size, System.Func<int, TGROUP> func_new_col, System.Action<TGROUP, int, T> func_add) where TGROUP : class { if (items == null) { throw new System.ArgumentNullException("items"); } if (group_size < 1 ) { throw new System.ArgumentOutOfRangeException("group_size"); } if (func_new_col == null) { throw new System.ArgumentNullException("func_new_col"); } if (func_add == null) { throw new System.ArgumentNullException("func_add"); } int cur_group_size = 0; TGROUP cur_group =null; foreach (var item in items) { if (cur_group_size==0) { if (cur_group == null) { cur_group = func_new_col(group_size); } else { throw new System.InvalidOperationException(); } } func_add(cur_group, cur_group_size, item); cur_group_size++; if (cur_group_size==group_size) { yield return cur_group; cur_group = null; cur_group_size = 0; } } if (cur_group_size>0) { if (cur_group==null) { throw new System.InvalidOperationException(); } yield return cur_group; } } public static IEnumerable<TGROUP> GroupByCount<T, TGROUP>(ICollection<T> items, ICollection<int> group_sizes, System.Func<int, TGROUP> func_new_col, System.Action<TGROUP, int, T> func_add) { if (items == null) { throw new System.ArgumentNullException("items"); } if (group_sizes == null) { throw new System.ArgumentNullException("group_sizes"); } if (func_new_col == null) { throw new System.ArgumentNullException("func_new_col"); } if (func_add == null) { throw new System.ArgumentNullException("func_add"); } int total_group_sizes = group_sizes.Sum(); if (total_group_sizes != items.Count) { throw new System.ArgumentException("group_sizes must account for all items"); } int items_added = 0; for (int group_index = 0; group_index < group_sizes.Count; group_index++) { int cur_group_size = group_sizes.ElementAt(group_index); if (cur_group_size < 0) { throw new System.ArgumentException("group_sizes contains a negative numver"); } var cur_group = func_new_col(cur_group_size); for (int row_index = 0; row_index < cur_group_size; row_index++) { var cur_item = items.ElementAt(items_added); func_add(cur_group, row_index, cur_item); items_added++; } yield return cur_group; } } public static IDictionary<K, List<V>> Bucketize<K, V>(IEnumerable<V> items, System.Func<V, K> func_get_key, IEqualityComparer<K> ieq) { if (items == null) { throw new System.ArgumentNullException("items"); } if (func_get_key == null) { throw new System.ArgumentNullException("func_get_key"); } var dic = new Dictionary<K, List<V>>(ieq); foreach (var item in items) { var key = func_get_key(item); List<V> list = null; bool found = dic.TryGetValue(key, out list); if (!found) { list = new List<V>(); dic[key] = list; } list.Add(item); } return dic; } public static IDictionary<K, List<V>> Bucketize<K, V>(IEnumerable<V> items, System.Func<V, K> func_get_key) { IEqualityComparer<K> ieq = null; return Bucketize<K, V>(items,func_get_key,ieq); } public static IDictionary<K, int> Histogram<K, V>(IEnumerable<V> items, System.Func<V, K> func_get_key, IEqualityComparer<K> ieq) { if (items == null) { throw new System.ArgumentNullException("items"); } if (func_get_key == null) { throw new System.ArgumentNullException("func_get_key"); } var dic = new Dictionary<K, int>(ieq); foreach (var item in items) { var key = func_get_key(item); int old_value = 0; bool found = dic.TryGetValue(key, out old_value); if (!found) { dic[key] = 1; } else { dic[key] = old_value + 1; } } return dic; } public static IDictionary<T, int> Histogram<T>(IEnumerable<T> items) { var dic = Histogram(items, i => i, null); return dic; } public static List<List<T>> Chunkify<T>(IEnumerable<T> items, int chunksize) { var chunks = new List<List<T>>(); List<T> cur_chunk = null; Chunkify(items, chunksize, () => { cur_chunk = new List<T>(chunksize); chunks.Add(cur_chunk); }, item => { cur_chunk.Add(item); }); return chunks; } public static void Chunkify<T>(IEnumerable<T> items, int chunksize, System.Action create_chunk, System.Action<T> add_item) { if (items == null) { throw new System.ArgumentNullException("items"); } if (chunksize < 1) { throw new System.ArgumentOutOfRangeException("chunksize"); } int item_count = 0; int curchunk_size = 0; foreach (T item in items) { if ((item_count % chunksize) == 0) { create_chunk(); curchunk_size = 0; } add_item(item); item_count++; curchunk_size++; } } } }