1using System; 2using System.Collections.Generic; 3using System.Text; 4 5// Taken from Mono sources, changed to work on C# 2.0 compilers 6 7// 8// Enumerable.cs 9// 10// Authors: 11// Marek Safar (marek.safar@gmail.com) 12// Antonello Provenzano <antonello@deveel.com> 13// Alejandro Serrano "Serras" (trupill@yahoo.es) 14// Jb Evain (jbevain@novell.com) 15// 16// Copyright (C) 2007 Novell, Inc (http://www.novell.com) 17// 18// Permission is hereby granted, free of charge, to any person obtaining 19// a copy of this software and associated documentation files (the 20// "Software"), to deal in the Software without restriction, including 21// without limitation the rights to use, copy, modify, merge, publish, 22// distribute, sublicense, and/or sell copies of the Software, and to 23// permit persons to whom the Software is furnished to do so, subject to 24// the following conditions: 25// 26// The above copyright notice and this permission notice shall be 27// included in all copies or substantial portions of the Software. 28// 29// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 30// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 31// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 32// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 33// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 34// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 35// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 36// 37 38// precious: http://www.hookedonlinq.com 39 40public delegate TResult Func<TResult>(); 41public delegate TResult Func<T, TResult>(T arg1); 42public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2); 43public delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3); 44public delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4); 45 46 47namespace Antlr.Runtime.JavaExtensions { 48 static class EnumerableExtensions { 49 50 #region Average 51 52 public static double Average(IEnumerable<int> source) { 53 return Average<int, long, double>(source, delegate(long a, int b) { return a + b; }, delegate(long a, long b) { return (double)a / (double)b; }); 54 } 55 56 static TResult Average<TElement, TAggregate, TResult>(IEnumerable<TElement> source, 57 Func<TAggregate, TElement, TAggregate> func, Func<TAggregate, long, TResult> result) 58 where TElement : struct 59 where TAggregate : struct 60 where TResult : struct { 61 Check.Source(source); 62 63 var total = default(TAggregate); 64 long counter = 0; 65 foreach (var element in source) { 66 total = func(total, element); 67 ++counter; 68 } 69 70 if (counter == 0) 71 throw new InvalidOperationException(); 72 73 return result(total, counter); 74 } 75 76 public static double Average(IEnumerable<double> source) { 77 return Average<double, double, double>(source, delegate(double a, double b) { return a + b; }, delegate(double a, long b) { return a / b; }); 78 } 79 80 #endregion 81 82 #region Contains 83 84 public static bool Contains<TSource>(IEnumerable<TSource> source, TSource value) { 85 var collection = source as ICollection<TSource>; 86 if (collection != null) 87 return collection.Contains(value); 88 89 return Contains<TSource>(source, value, null); 90 } 91 92 public static bool Contains<TSource>(IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer) { 93 Check.Source(source); 94 95 if (comparer == null) 96 comparer = EqualityComparer<TSource>.Default; 97 98 foreach (var element in source) 99 if (comparer.Equals(element, value)) 100 return true; 101 102 return false; 103 } 104 #endregion 105 106 #region DefaultIfEmpty 107 108 public static IEnumerable<TSource> DefaultIfEmpty<TSource>(IEnumerable<TSource> source) { 109 return DefaultIfEmpty(source, default(TSource)); 110 } 111 112 public static IEnumerable<TSource> DefaultIfEmpty<TSource>(IEnumerable<TSource> source, TSource defaultValue) { 113 Check.Source(source); 114 115 return CreateDefaultIfEmptyIterator(source, defaultValue); 116 } 117 118 static IEnumerable<TSource> CreateDefaultIfEmptyIterator<TSource>(IEnumerable<TSource> source, TSource defaultValue) { 119 bool empty = true; 120 foreach (TSource item in source) { 121 empty = false; 122 yield return item; 123 } 124 125 if (empty) 126 yield return defaultValue; 127 } 128 129 #endregion 130 131 #region Max 132 133 public static int Max(IEnumerable<int> source) { 134 Check.Source(source); 135 136 return Iterate(source, int.MinValue, delegate(int a, int b){return Math.Max(a, b);}); 137 } 138 139 static U Iterate<T, U>(IEnumerable<T> source, U initValue, Func<T, U, U> selector) { 140 bool empty = true; 141 foreach (var element in source) { 142 initValue = selector(element, initValue); 143 empty = false; 144 } 145 146 if (empty) 147 throw new InvalidOperationException(); 148 149 return initValue; 150 } 151 152 #endregion 153 154 #region Min 155 156 public static int Min(IEnumerable<int> source) { 157 Check.Source(source); 158 159 return Iterate(source, int.MaxValue, delegate(int a, int b) { return Math.Min(a, b); }); 160 } 161 162 #endregion 163 164 #region Select 165 166 public static IEnumerable<TResult> Select<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> selector) { 167 Check.SourceAndSelector(source, selector); 168 169 return CreateSelectIterator(source, selector); 170 } 171 172 static IEnumerable<TResult> CreateSelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> selector) { 173 foreach (var element in source) 174 yield return selector(element); 175 } 176 177 public static IEnumerable<TResult> Select<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, TResult> selector) { 178 Check.SourceAndSelector(source, selector); 179 180 return CreateSelectIterator(source, selector); 181 } 182 183 static IEnumerable<TResult> CreateSelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, TResult> selector) { 184 int counter = 0; 185 foreach (TSource element in source) { 186 yield return selector(element, counter); 187 counter++; 188 } 189 } 190 191 #endregion 192 193 #region SelectMany 194 195 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(IEnumerable<TSource> source, 196 Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector) { 197 Check.SourceAndCollectionSelectors(source, collectionSelector, selector); 198 199 return CreateSelectManyIterator(source, collectionSelector, selector); 200 } 201 202 public static IEnumerable<TResult> SelectMany<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector) { 203 Check.SourceAndSelector(source, selector); 204 205 return CreateSelectManyIterator(source, selector); 206 } 207 208 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TCollection, TResult>(IEnumerable<TSource> source, 209 Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector) { 210 int counter = 0; 211 foreach (TSource element in source) 212 foreach (TCollection collection in collectionSelector(element, counter++)) 213 yield return selector(element, collection); 214 } 215 216 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector) { 217 int counter = 0; 218 foreach (TSource element in source) { 219 foreach (TResult item in selector(element, counter)) 220 yield return item; 221 counter++; 222 } 223 } 224 225 #endregion 226 227 #region Sum 228 229 public static int Sum(IEnumerable<int> source) { 230 Check.Source(source); 231 232 return Sum<int, int>(source, delegate(int a, int b) { return checked(a + b); }); 233 } 234 235 static TR Sum<TA, TR>(IEnumerable<TA> source, Func<TR, TA, TR> selector) { 236 TR total = default(TR); 237 foreach (var element in source) { 238 total = selector(total, element); 239 } 240 241 return total; 242 } 243 244 #endregion 245 246 #region Take 247 248 public static IEnumerable<TSource> Take<TSource>(IEnumerable<TSource> source, int count) { 249 Check.Source(source); 250 251 return CreateTakeIterator(source, count); 252 } 253 254 static IEnumerable<TSource> CreateTakeIterator<TSource>(IEnumerable<TSource> source, int count) { 255 if (count <= 0) 256 yield break; 257 258 int counter = 0; 259 foreach (TSource element in source) { 260 yield return element; 261 262 if (++counter == count) 263 yield break; 264 } 265 } 266 267 #endregion 268 269 #region ToArray 270 271 public static TSource[] ToArray<TSource>(IEnumerable<TSource> source) { 272 Check.Source(source); 273 274 var collection = source as ICollection<TSource>; 275 if (collection != null) { 276 var array = new TSource[collection.Count]; 277 collection.CopyTo(array, 0); 278 return array; 279 } 280 281 return new List<TSource>(source).ToArray(); 282 } 283 284 #endregion 285 } 286} 287