using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace Core.Common.Utils.Collections { public static class EnumerableExtensions { /// /// Returns the type of the (first) element in the Enumerable. Returns null if the enumerable is empty. /// /// /// public static Type GetInnerType(this IEnumerable source) { foreach (var item in source) { return item.GetType(); } return null; } /// /// Adds elements to enumerable (replaces .Concat(new []{element1, element2 ...}) ) /// /// Type of item /// Collection to add the elements to /// Items to add /// with public static IEnumerable Plus(this IEnumerable collection, params T[] items) { return collection.Concat(items); } public static void ForEach(this IEnumerable source, Action action) { foreach (var item in source) { action(item); } } public static IList AsList(this IEnumerable enumerable) { return enumerable as IList ?? enumerable.ToList(); } //borrowed: http://stackoverflow.com/questions/3907408/dotnet-flatten-a-tree-list-of-lists-with-one-statement public static IEnumerable Flatten(this IEnumerable source, Func> childrenSelector) { foreach (var item in source) { yield return item; foreach (var child in childrenSelector(item).Flatten(childrenSelector)) { yield return child; } } } public static void ForEach(this IEnumerable source, Action action) { var i = 0; foreach (var item in source) { action(item, i); i++; } } public static bool HasExactlyOneValue(this IEnumerable values) { int i = 0; foreach (object o in values) { i++; if (i > 1) { break; } } return (i == 1); } public static IEnumerable> SplitInGroups(this IEnumerable list, int groupSize) { if (groupSize <= 0) { throw new ArgumentException("GroupSize must be greater than 0", "groupSize"); } var countSoFar = 0; var group = new List(); foreach (var elem in list) { group.Add(elem); if (++countSoFar == groupSize) { yield return group; countSoFar = 0; group = new List(); } } if (group.Count > 0) { yield return group; } } /// /// Returns values1 except values2. /// /// /// /// public static IEnumerable Except(this IEnumerable values1, IList values2) { foreach (object o in values1) { if (!values2.Contains(o)) { yield return o; } } } public static string ConvertToString(this IEnumerable values) { return String.Join(",", values.Select(v => v.ToString()).ToArray()); } public static IEnumerable QuickSort(this IEnumerable list) where T : IComparable { if (!list.Any()) { return Enumerable.Empty(); } T pivot = (T) list.First(); IEnumerable smaller = list.Where(item => item.CompareTo(pivot) <= 0).QuickSort(); IEnumerable larger = list.Where(item => item.CompareTo(pivot) > 0).QuickSort(); return smaller.Concat(new[] { pivot }).Concat(larger); } public static IEnumerable Substract(this IEnumerable index1, IEnumerable index2) { var i1 = index1.GetEnumerator(); var i2 = index2.GetEnumerator(); while (i1.MoveNext() && i2.MoveNext()) { yield return i1.Current - i2.Current; } } public static IEnumerable AddValue(this IEnumerable index1, IEnumerable index2) { var i1 = index1.GetEnumerator(); var i2 = index2.GetEnumerator(); while (i1.MoveNext() && i2.MoveNext()) { yield return i1.Current + i2.Current; } } public static IEnumerable AddValue(this IEnumerable index1, int value) { var i1 = index1.GetEnumerator(); while (i1.MoveNext()) { yield return i1.Current + value; } } public static IEnumerable Substract(this IEnumerable index1, int value) { var i1 = index1.GetEnumerator(); while (i1.MoveNext()) { yield return i1.Current - value; } } // From http://community.bartdesmet.net/blogs/bart/archive/2008/11/03/c-4-0-feature-focus-part-3-intermezzo-linq-s-new-zip-operator.aspx public static IEnumerable Zip(this IEnumerable first, IEnumerable second, Func func) { if (first == null) { throw new ArgumentNullException("first"); } if (second == null) { throw new ArgumentNullException("second"); } if (func == null) { throw new ArgumentNullException("func"); } using (var ie1 = first.GetEnumerator()) { using (var ie2 = second.GetEnumerator()) { while (ie1.MoveNext() && ie2.MoveNext()) { yield return func(ie1.Current, ie2.Current); } } } } public static IEnumerable> Zip(this IEnumerable first, IEnumerable second) { return first.Zip(second, (f, s) => new Tuple(f, s)); } public static bool HasUniqueValues(this IEnumerable enumerable) { return enumerable.Distinct().Count() == enumerable.Count(); } public static bool IsMonotonousDescending(this IEnumerable enumerable) where T : IComparable { T previousValue = default(T); foreach (var value in enumerable) { if (previousValue != null && !previousValue.Equals(default(T))) { if (value.CompareTo(previousValue) > 0) { return false; //the next value is smaller than the previous...not monotonous ascending } } previousValue = value; } return true; } public static bool IsMonotonousAscending(this IEnumerable enumerable) where T : IComparable { T previousValue = default(T); foreach (var value in enumerable) { if (previousValue != null && !previousValue.Equals(default(T))) { if (value.CompareTo(previousValue) < 0) { return false; //the next value is smaller than the previous...not monotonous ascending } } previousValue = value; } return true; } /* public static void Times(this int times,Action action) { for (int i =0;i /// Returns the number of elements in a sequence. /// /// A sequence that contains elements to be counted. /// The number of elements in the input sequence. /// source is null. /// The number of elements in source is larger than /// public static int Count(this IEnumerable source) { return Enumerable.Count(source.Cast()); } } }