| | | 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 | | } |