using System; using System.Collections.Generic; using System.Text; // Taken from Mono sources, changed to work on C# 2.0 compilers // // Enumerable.cs // // Authors: // Marek Safar (marek.safar@gmail.com) // Antonello Provenzano <antonello@deveel.com> // Alejandro Serrano "Serras" (trupill@yahoo.es) // Jb Evain (jbevain@novell.com) // // Copyright (C) 2007 Novell, Inc (http://www.novell.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // precious: http://www.hookedonlinq.com public delegate TResult Func<TResult>(); public delegate TResult Func<T, TResult>(T arg1); public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2); public delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3); public delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4); namespace Antlr.Runtime.JavaExtensions { static class EnumerableExtensions { #region Average public static double Average(IEnumerable<int> source) { return Average<int, long, double>(source, delegate(long a, int b) { return a + b; }, delegate(long a, long b) { return (double)a / (double)b; }); } static TResult Average<TElement, TAggregate, TResult>(IEnumerable<TElement> source, Func<TAggregate, TElement, TAggregate> func, Func<TAggregate, long, TResult> result) where TElement : struct where TAggregate : struct where TResult : struct { Check.Source(source); var total = default(TAggregate); long counter = 0; foreach (var element in source) { total = func(total, element); ++counter; } if (counter == 0) throw new InvalidOperationException(); return result(total, counter); } public static double Average(IEnumerable<double> source) { return Average<double, double, double>(source, delegate(double a, double b) { return a + b; }, delegate(double a, long b) { return a / b; }); } #endregion #region Contains public static bool Contains<TSource>(IEnumerable<TSource> source, TSource value) { var collection = source as ICollection<TSource>; if (collection != null) return collection.Contains(value); return Contains<TSource>(source, value, null); } public static bool Contains<TSource>(IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer) { Check.Source(source); if (comparer == null) comparer = EqualityComparer<TSource>.Default; foreach (var element in source) if (comparer.Equals(element, value)) return true; return false; } #endregion #region DefaultIfEmpty public static IEnumerable<TSource> DefaultIfEmpty<TSource>(IEnumerable<TSource> source) { return DefaultIfEmpty(source, default(TSource)); } public static IEnumerable<TSource> DefaultIfEmpty<TSource>(IEnumerable<TSource> source, TSource defaultValue) { Check.Source(source); return CreateDefaultIfEmptyIterator(source, defaultValue); } static IEnumerable<TSource> CreateDefaultIfEmptyIterator<TSource>(IEnumerable<TSource> source, TSource defaultValue) { bool empty = true; foreach (TSource item in source) { empty = false; yield return item; } if (empty) yield return defaultValue; } #endregion #region Max public static int Max(IEnumerable<int> source) { Check.Source(source); return Iterate(source, int.MinValue, delegate(int a, int b){return Math.Max(a, b);}); } static U Iterate<T, U>(IEnumerable<T> source, U initValue, Func<T, U, U> selector) { bool empty = true; foreach (var element in source) { initValue = selector(element, initValue); empty = false; } if (empty) throw new InvalidOperationException(); return initValue; } #endregion #region Min public static int Min(IEnumerable<int> source) { Check.Source(source); return Iterate(source, int.MaxValue, delegate(int a, int b) { return Math.Min(a, b); }); } #endregion #region Select public static IEnumerable<TResult> Select<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> selector) { Check.SourceAndSelector(source, selector); return CreateSelectIterator(source, selector); } static IEnumerable<TResult> CreateSelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> selector) { foreach (var element in source) yield return selector(element); } public static IEnumerable<TResult> Select<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, TResult> selector) { Check.SourceAndSelector(source, selector); return CreateSelectIterator(source, selector); } static IEnumerable<TResult> CreateSelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, TResult> selector) { int counter = 0; foreach (TSource element in source) { yield return selector(element, counter); counter++; } } #endregion #region SelectMany public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector) { Check.SourceAndCollectionSelectors(source, collectionSelector, selector); return CreateSelectManyIterator(source, collectionSelector, selector); } public static IEnumerable<TResult> SelectMany<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector) { Check.SourceAndSelector(source, selector); return CreateSelectManyIterator(source, selector); } static IEnumerable<TResult> CreateSelectManyIterator<TSource, TCollection, TResult>(IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector) { int counter = 0; foreach (TSource element in source) foreach (TCollection collection in collectionSelector(element, counter++)) yield return selector(element, collection); } static IEnumerable<TResult> CreateSelectManyIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector) { int counter = 0; foreach (TSource element in source) { foreach (TResult item in selector(element, counter)) yield return item; counter++; } } #endregion #region Sum public static int Sum(IEnumerable<int> source) { Check.Source(source); return Sum<int, int>(source, delegate(int a, int b) { return checked(a + b); }); } static TR Sum<TA, TR>(IEnumerable<TA> source, Func<TR, TA, TR> selector) { TR total = default(TR); foreach (var element in source) { total = selector(total, element); } return total; } #endregion #region Take public static IEnumerable<TSource> Take<TSource>(IEnumerable<TSource> source, int count) { Check.Source(source); return CreateTakeIterator(source, count); } static IEnumerable<TSource> CreateTakeIterator<TSource>(IEnumerable<TSource> source, int count) { if (count <= 0) yield break; int counter = 0; foreach (TSource element in source) { yield return element; if (++counter == count) yield break; } } #endregion #region ToArray public static TSource[] ToArray<TSource>(IEnumerable<TSource> source) { Check.Source(source); var collection = source as ICollection<TSource>; if (collection != null) { var array = new TSource[collection.Count]; collection.CopyTo(array, 0); return array; } return new List<TSource>(source).ToArray(); } #endregion } }