Advertisement
Guest User

RangeEnumeration

a guest
Mar 27th, 2022
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.97 KB | None | 0 0
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5.  
  6. namespace PersonalUtilities;
  7. /// <summary>
  8. /// Provides extension methods to enumerate a <see cref="Range"/> using foreach and LINQ.
  9. /// </summary>
  10. public static class RangeEnumerable
  11. {
  12.     /// <summary>
  13.     /// Enumerates a <see cref="Range"/>.
  14.     /// </summary>
  15.     public struct Enumerator : IEnumerator<int>, IEnumerable<int>
  16.     {
  17.         private int current;
  18.         private int state;
  19.         private readonly int start;
  20.         private readonly int end;
  21.         private readonly int direction;
  22.         public int Current => current;
  23.         public bool MoveNext()
  24.         {
  25.             switch (state)
  26.             {
  27.                 case 0:
  28.                     if (direction == 1)
  29.                         state = 1;
  30.                     else if(direction == -1)
  31.                         state = 2;
  32.                     return true;
  33.                 case 1:
  34.                     current++;
  35.                     if (current >= end)
  36.                         state = 4;
  37.                     return true;
  38.                 case 2:
  39.                     current--;
  40.                     if (current <= end)
  41.                         state = 4;
  42.                     return true;
  43.                 case 3:
  44.                     state = 4;
  45.                     return true;
  46.                 case 4:
  47.                     return false;
  48.                 default:
  49.                     return false;
  50.             }
  51.         }
  52.         public void Dispose() { }
  53.         internal Enumerator(Range range) : this(range.Start, range.End) { }
  54.         internal Enumerator(Index start, Index end) : this(start.GetOffset(0), end.GetOffset(0)) { }
  55.         internal Enumerator(int start, int end)
  56.         {
  57.             this.direction = Math.Sign(end - start);
  58.             this.state = direction == 0 ? 3 : 0;
  59.             this.current = start;
  60.             this.start = start;
  61.             this.end = end;
  62.         }
  63.         object IEnumerator.Current => current;
  64.         void IEnumerator.Reset()
  65.         {
  66.             current = start;
  67.             state = direction == 0 ? 3 : 0;
  68.         }
  69.         IEnumerator<int> IEnumerable<int>.GetEnumerator() => this;
  70.         IEnumerator IEnumerable.GetEnumerator() => this;
  71.     }
  72.  
  73.     /// <summary>
  74.     /// Allows <see cref="Range"/> to be enumerated with foreach.
  75.     /// </summary>
  76.     /// <param name="range">The <see cref="Range"/> to enumerate.</param>
  77.     /// <returns>
  78.     /// Returns an enumerator that iterates through the integers of a <see cref="Range"/>.
  79.     /// </returns>
  80.     /// <seealso cref="AsEnumerable(Range)"/>
  81.     public static Enumerator GetEnumerator(this Range range)
  82.         => new(range);
  83.  
  84.     /// <summary>
  85.     /// Allows <see cref="Range"/> to be used with LINQ Extension methods.
  86.     /// </summary>
  87.     /// <param name="range">The <see cref="Range"/> to enumerate.</param>
  88.     /// <returns>
  89.     /// An <see cref="IEnumerable{int}"/> whose elements are each integer of a <see cref="Range"/>.
  90.     /// </returns>
  91.     /// <seealso cref="GetEnumerator(Range)"/>
  92.     public static IEnumerable<int> AsEnumerable(this Range range)
  93.         => new Enumerator(range);
  94.  
  95.     /// <summary>
  96.     /// Projects each integer of a range into a new form.
  97.     /// </summary>
  98.     /// <inheritdoc cref="Enumerable.Select{TSource, TResult}(IEnumerable{TSource}, Func{TSource, TResult})"/>
  99.     /// <typeparam name="TResult"></typeparam>
  100.     /// <param name="range"></param>
  101.     /// <param name="selector"></param>
  102.     public static IEnumerable<TResult> Select<TResult>(this Range range, Func<int, TResult> selector)
  103.         => Enumerable.Select(range.AsEnumerable(), selector);
  104.  
  105.     /// <summary>
  106.     /// Projects each integer of a range into a new form by incorporating the element's index.
  107.     /// </summary>
  108.     /// <inheritdoc cref="Enumerable.Select{TSource, TResult}(IEnumerable{TSource}, Func{TSource, int, TResult})"/>
  109.     /// <typeparam name="TResult"></typeparam>
  110.     /// <param name="range"></param>
  111.     /// <param name="selector"></param>
  112.     public static IEnumerable<TResult> Select<TResult>(this Range range, Func<int, int, TResult> selector)
  113.         => Enumerable.Select(range.AsEnumerable(), selector);
  114.  
  115.     /// <summary>
  116.     /// Creates an array of integers from a <see cref="Range"/>.
  117.     /// </summary>
  118.     /// <param name="range">
  119.     /// A <see cref="Range"/> from which the array is created.
  120.     /// </param>
  121.     /// <returns></returns>
  122.     public static int[] ToArray(this Range range)
  123.         => range.AsEnumerable().ToArray();
  124.  
  125.     /// <summary>
  126.     /// Creates a <see cref="List{T}"/> of integers from a <see cref="Range"/>.
  127.     /// </summary>
  128.     /// <param name="range">
  129.     /// A <see cref="Range"/> from which the <see cref="List{T}"/> is created.
  130.     /// </param>
  131.     /// <returns>A <see cref="List{T}"/> of <see cref="int"/>.</returns>
  132.     public static List<int> ToList(this Range range)
  133.         => range.AsEnumerable().ToList();
  134. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement