| | 1 | | namespace Towel; |
| | 2 | |
|
| | 3 | | /// <summary>Static helper methods for arrays.</summary> |
| | 4 | | public static class ArrayHelper |
| | 5 | | { |
| | 6 | | /// <summary>Constructs a new 1D array from a sequence of ranges.</summary> |
| | 7 | | /// <returns>A new 1D array from the sequence of ranges.</returns> |
| | 8 | | /// <inheritdoc cref="NewFromRanges{T, TSelect}(TSelect, Range[])"/> |
| | 9 | | public static int[] NewFromRanges(params Range[] ranges) => |
| 55 | 10 | | NewFromRanges<int, Identity<int>>(default, ranges); |
| | 11 | |
|
| | 12 | | /// <inheritdoc cref="NewFromRanges{T, TSelect}(TSelect, Range[])"/> |
| | 13 | | public static T[] NewFromRanges<T>(Func<int, T> select, params Range[] ranges) => |
| 0 | 14 | | NewFromRanges<T, SFunc<int, T>>(select, ranges); |
| | 15 | |
|
| | 16 | | /// <summary>Constructs a new 1D array from a sequence of ranges and a selction method.</summary> |
| | 17 | | /// <typeparam name="T">The element type of the array to construct.</typeparam> |
| | 18 | | /// <typeparam name="TSelect">The type of method for selecting <typeparamref name="T"/> from <see cref="int"/> values. |
| | 19 | | /// <param name="select">The method for selecting <typeparamref name="T"/> from <see cref="int"/> values.</param> |
| | 20 | | /// <param name="ranges">The ranges to construct the array from.</param> |
| | 21 | | /// <returns>A new 1D array from the sequence of ranges and the selction method.</returns> |
| | 22 | | public static T[] NewFromRanges<T, TSelect>(TSelect select, params Range[] ranges) |
| | 23 | | where TSelect : struct, IFunc<int, T> |
| 55 | 24 | | { |
| 55 | 25 | | if (ranges is null) throw new ArgumentNullException(nameof(ranges)); |
| 55 | 26 | | int length = 0; |
| 449 | 27 | | foreach (var range in ranges) |
| 142 | 28 | | { |
| 142 | 29 | | { |
| 142 | 30 | | if (sourceof(range.Start.IsFromEnd, out string c1)) |
| 0 | 31 | | { |
| 0 | 32 | | throw new ArgumentException(c1, nameof(ranges)); |
| | 33 | | } |
| 142 | 34 | | } |
| 426 | 35 | | { if (sourceof(range.End.IsFromEnd, out string c2)) throw new ArgumentException(c2, nameof(ranges)); } |
| 142 | 36 | | if (range.Start.Value < range.End.Value) |
| 63 | 37 | | { |
| 63 | 38 | | length += range.End.Value - range.Start.Value; |
| 63 | 39 | | } |
| | 40 | | else |
| 79 | 41 | | { |
| 79 | 42 | | length += range.Start.Value - range.End.Value; |
| 79 | 43 | | } |
| 142 | 44 | | } |
| 55 | 45 | | if (length is 0) |
| 3 | 46 | | { |
| 3 | 47 | | return Array.Empty<T>(); |
| | 48 | | } |
| 52 | 49 | | T[] result = new T[length]; |
| 52 | 50 | | int index = 0; |
| 434 | 51 | | foreach (var range in ranges) |
| 139 | 52 | | { |
| 139 | 53 | | if (range.Start.Value < range.End.Value) |
| 63 | 54 | | { |
| 70846 | 55 | | for (int i = range.Start.Value; i < range.End.Value; i++) |
| 35360 | 56 | | { |
| 35360 | 57 | | result[index++] = select.Invoke(i); |
| 35360 | 58 | | } |
| 63 | 59 | | } |
| | 60 | | else |
| 76 | 61 | | { |
| 1538 | 62 | | for (int i = range.Start.Value; i > range.End.Value; i--) |
| 693 | 63 | | { |
| 693 | 64 | | result[index++] = select.Invoke(i); |
| 693 | 65 | | } |
| 76 | 66 | | } |
| 139 | 67 | | } |
| 52 | 68 | | return result; |
| 55 | 69 | | } |
| | 70 | | } |