Blog Archive

Wednesday, April 4

    7 public static class CollectionHelper
    8 {
    9     public static IEnumerable<T> Enumerate<T>(params T[] args)
   10     {
   11         if (args == null)
   12             throw new ArgumentNullException("args");
   13 
   14         foreach (T arg in args)
   15             yield return arg;
   16     }
   17 
   18     public static T First<T>(IEnumerable<T> source)
   19     {
   20         return First(source, ReturnTrue);
   21     }
   22 
   23     public static T First<T>(IEnumerable<T> source, Func<T, bool> predicate)
   24     {
   25         T result;
   26         if (!TryFindFirst(source, out result, predicate))
   27             throw new InvalidOperationException("Source sequence empty or no items satisfy predicate.");
   28 
   29         return result;
   30     }
   31 
   32     public static T FirstOrDefault<T>(IEnumerable<T> source)
   33     {
   34         return FirstOrDefault(source, ReturnTrue);
   35     }
   36 
   37     public static T FirstOrDefault<T>(IEnumerable<T> source, Func<T, bool> predicate)
   38     {
   39         T result;
   40         TryFindFirst(source, out result, predicate);
   41         return result;
   42     }
   43 
   44     public static bool TryFindFirst<T>(IEnumerable<T> source, out T result)
   45     {
   46         return TryFindFirst(source, out result, ReturnTrue);
   47     }
   48 
   49     public static bool TryFindFirst<T>(IEnumerable<T> source, out T result, Func<T, bool> predicate)
   50     {
   51         if (source == null)
   52             throw new ArgumentNullException("source");
   53         if (predicate == null)
   54             throw new ArgumentNullException("predicate");
   55 
   56         foreach (T item in source)
   57         {
   58             if (predicate(item))
   59             {
   60                 result = item;
   61                 return true;
   62             }
   63         }
   64 
   65         result = default(T);
   66         return false;
   67     }
   68 
   69     public static IEnumerable<TOut> Map<T, TOut>(IEnumerable<T> source, Func<T, TOut> converter)
   70     {
   71         if (source == null)
   72             throw new ArgumentNullException("source");
   73         if (converter == null)
   74             throw new ArgumentNullException("fn");
   75 
   76         foreach (T item in source)
   77             yield return converter(item);
   78     }
   79 
   80     public static IEnumerable<TOut> Zip<TLeft, TRight, TOut>(IEnumerable<TLeft> left, IEnumerable<TRight> right, Func<TLeft, TRight, TOut> fn)
   81     {
   82         if (left == null)
   83             throw new ArgumentNullException("left");
   84         if (right == null)
   85             throw new ArgumentNullException("right");
   86         if (fn == null)
   87             throw new ArgumentNullException("fn");
   88 
   89         using (IEnumerator<TLeft> leftEnumerator = left.GetEnumerator())
   90         using (IEnumerator<TRight> rightEnumerator = right.GetEnumerator())
   91         {
   92             while (true)
   93             {
   94                 bool leftMoved = leftEnumerator.MoveNext();
   95 
   96                 if (!(leftMoved == rightEnumerator.MoveNext()))
   97                     throw new InvalidOperationException("Sequences are of incompatible lengths.");
   98 
   99                 if (!leftMoved)
  100                     break;
  101 
  102                 yield return fn(leftEnumerator.Current, rightEnumerator.Current);
  103             }
  104         }
  105     }
  106 
  107     private static bool ReturnTrue<T>(T ignored)
  108     {
  109         return true;
  110     }
  111 }