< Summary

Class:Towel.DataStructures.ListArray<T>
Assembly:Towel
File(s):File 1: /home/runner/work/Towel/Towel/Sources/Towel/DataStructures/List.cs
Covered lines:75
Uncovered lines:70
Coverable lines:145
Total lines:655
Line coverage:51.7% (75 of 145)
Covered branches:25
Total branches:60
Branch coverage:41.6% (25 of 60)

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
File 1: .ctor()100%1100%
File 1: .ctor(...)50%275%
File 1: .ctor(...)100%10%
File 1: .ctor(...)100%10%
File 1: get_Item(...)50%466.66%
File 1: set_Item(...)0%40%
File 1: get_Count()100%1100%
File 1: get_CurrentCapacity()100%10%
File 1: TryAdd(...)75%481.81%
File 1: Add(...)0%100%
File 1: Clear()100%10%
File 1: Clone()100%10%
File 1: Remove(...)100%2100%
File 1: RemoveWithoutShrink(...)66.66%680%
File 1: RemoveAll(...)50%257.14%
File 1: RemoveAllWithoutShrink(...)83.33%688.23%
File 1: RemoveFirst(...)0%40%
File 1: RemoveFirstWithoutShrink(...)0%20%
File 1: RemoveFirstWithoutShrink(...)0%40%
File 1: TryRemoveFirst(...)100%10%
File 1: TryRemoveFirst(...)100%4100%
File 1: StepperBreak(...)100%1100%
File 1: System.Collections.IEnumerable.GetEnumerator()100%10%
File 1: GetEnumerator()100%2100%
File 1: ToArray()50%2100%
File 1: Trim()0%20%

File(s)

/home/runner/work/Towel/Towel/Sources/Towel/DataStructures/List.cs

#LineLine coverage
 1namespace Towel.DataStructures;
 2
 3/// <summary>A primitive dynamic sized data structure.</summary>
 4/// <typeparam name="T">The type of items to store in the list.</typeparam>
 5public interface IList<T> : IDataStructure<T>,
 6  DataStructure.IAddable<T>,
 7  DataStructure.ICountable,
 8  DataStructure.IClearable
 9{
 10  #region Methods
 11
 12  /// <summary>Tries to remove the first predicated value if the value exists.</summary>
 13  /// <typeparam name="TPredicate">The type of predicate to determine removal.</typeparam>
 14  /// <param name="exception">The exception that occurred if the remove failed.</param>
 15  /// <param name="predicate">The predicate to determine removal.</param>
 16  /// <returns>True if the value was removed. False if the value did not exist.</returns>
 17#warning TODO: convert to (bool Success, Exception Exception) return value?
 18  bool TryRemoveFirst<TPredicate>(out Exception? exception, TPredicate predicate = default)
 19    where TPredicate : struct, IFunc<T, bool>;
 20
 21  /// <summary>Removes all occurences of predicated values from the list.</summary>
 22  /// <typeparam name="TPredicate">The type of predicate to determine removals.</typeparam>
 23  /// <param name="predicate">The predicate to determine removals.</param>
 24  void RemoveAll<TPredicate>(TPredicate predicate = default)
 25    where TPredicate : struct, IFunc<T, bool>;
 26
 27  #endregion
 28}
 29
 30/// <summary>Contains static extension methods for IList types.</summary>
 31public static class List
 32{
 33  #region Extensions Methods
 34
 35  /// <summary>Removes all predicated values from an <see cref="IList{T}"/>.</summary>
 36  /// <typeparam name="T">The generic type of values inside the <see cref="IList{T}"/>.</typeparam>
 37  /// <param name="iList">The <see cref="IList{T}"/> to remove values from.</param>
 38  /// <param name="predicate">The predicate for selecting removals from the <see cref="IList{T}"/>.</param>
 39  public static void RemoveAll<T>(this IList<T> iList, Func<T, bool> predicate) =>
 40    iList.RemoveAll<SFunc<T, bool>>(predicate);
 41
 42  /// <summary>Tries to removes the first predicated value from an <see cref="IList{T}"/>.</summary>
 43  /// <typeparam name="T">The generic type of values inside the <see cref="IList{T}"/>.</typeparam>
 44  /// <param name="iList">The <see cref="IList{T}"/> to remove an element from.</param>
 45  /// <param name="predicate">The predicate for selecting the removal from the <see cref="IList{T}"/>.</param>
 46  /// <returns>True if the predicated element was found and removed. False if not.</returns>
 47  public static bool TryRemoveFirst<T>(this IList<T> iList, Func<T, bool> predicate) =>
 48    iList.TryRemoveFirst<SFunc<T, bool>>(out _, predicate);
 49
 50  /// <summary>Tries to removes the first predicated value from an <see cref="IList{T}"/>.</summary>
 51  /// <typeparam name="T">The generic type of values inside the <see cref="IList{T}"/>.</typeparam>
 52  /// <param name="iList">The <see cref="IList{T}"/> to remove an element from.</param>
 53  /// <param name="predicate">The predicate for selecting the removal from the <see cref="IList{T}"/>.</param>
 54  /// <param name="exception">The exception that occured if the removal failed.</param>
 55  /// <returns>True if the predicated element was found and removed. False if not.</returns>
 56  public static bool TryRemoveFirst<T>(this IList<T> iList, Func<T, bool> predicate, out Exception? exception) =>
 57    iList.TryRemoveFirst<SFunc<T, bool>>(out exception, predicate);
 58
 59  /// <summary>Removes the first equality by object reference.</summary>
 60  /// <typeparam name="T">The generic type of values inside the <see cref="IList{T}"/>.</typeparam>
 61  /// <param name="iList">The list to remove the value from.</param>
 62  /// <param name="predicate">The predicate to determine removal.</param>
 63  public static void RemoveFirst<T>(this IList<T> iList, Func<T, bool> predicate)
 64  {
 65    if (!iList.TryRemoveFirst<SFunc<T, bool>>(out Exception? exception, predicate))
 66    {
 67      throw exception ?? new ArgumentNullException(nameof(exception), $"{nameof(TryRemoveFirst)} failed but the {nameof(
 68    }
 69  }
 70
 71  /// <summary>Removes the first occurence of an item in the list.</summary>
 72  /// <typeparam name="T">The generic type of values inside the <see cref="IList{T}"/>.</typeparam>
 73  /// <param name="iList">The list to remove the value from.</param>
 74  /// <param name="value">The value to remove the first occurence of.</param>
 75  public static void RemoveFirst<T>(this IList<T> iList, T value)
 76  {
 77    iList.RemoveFirst(value, Equate);
 78  }
 79
 80  /// <summary>Removes the first occurence of an item in the list.</summary>
 81  /// <typeparam name="T">The generic type of values inside the <see cref="IList{T}"/>.</typeparam>
 82  /// <param name="iList">The list to remove the value from.</param>
 83  /// <param name="value">The value to remove the first occurence of.</param>
 84  /// <param name="equate">The delegate for performing equality checks.</param>
 85  public static void RemoveFirst<T>(this IList<T> iList, T value, Func<T, T, bool> equate)
 86  {
 87    iList.RemoveFirst(x => equate(x, value));
 88  }
 89
 90  /// <summary>Removes the first occurence of an item in the list or returns false.</summary>
 91  /// <typeparam name="T">The generic type of values inside the <see cref="IList{T}"/>.</typeparam>
 92  /// <param name="iList">The list to remove the value from.</param>
 93  /// <param name="value">The value to remove the first occurence of.</param>
 94  /// <returns>True if the item was found and removed; False if not.</returns>
 95  public static bool TryRemoveFirst<T>(this IList<T> iList, T value)
 96  {
 97    return iList.TryRemoveFirst(value, Equate);
 98  }
 99
 100  /// <summary>Removes the first occurence of an item in the list or returns false.</summary>
 101  /// <typeparam name="T">The generic type of values inside the <see cref="IList{T}"/>.</typeparam>
 102  /// <param name="iList">The list to remove the value from.</param>
 103  /// <param name="value">The value to remove the first occurence of.</param>
 104  /// <param name="equate">The delegate for performing equality checks.</param>
 105  /// <returns>True if the item was found and removed; False if not.</returns>
 106  public static bool TryRemoveFirst<T>(this IList<T> iList, T value, Func<T, T, bool> equate)
 107  {
 108    return iList.TryRemoveFirst(x => equate(x, value));
 109  }
 110
 111  /// <summary>Removes all occurences of an item in the list.</summary>
 112  /// <typeparam name="T">The generic type of values inside the <see cref="IList{T}"/>.</typeparam>
 113  /// <param name="iList">The list to remove the values from.</param>
 114  /// <param name="value">The value to remove all occurences of.</param>
 115  public static void RemoveAll<T>(this IList<T> iList, T value)
 116  {
 117    iList.RemoveAll(value, Equate);
 118  }
 119
 120  /// <summary>Removes all occurences of an item in the list.</summary>
 121  /// <typeparam name="T">The generic type of values inside the <see cref="IList{T}"/>.</typeparam>
 122  /// <param name="iList">The list to remove the values from.</param>
 123  /// <param name="value">The value to remove all occurences of.</param>
 124  /// <param name="equate">The delegate for performing equality checks.</param>
 125  public static void RemoveAll<T>(this IList<T> iList, T value, Func<T?, T, bool> equate)
 126  {
 127    iList.RemoveAll(x => equate(x, value));
 128  }
 129
 130  #endregion
 131}
 132
 133/// <summary>Implements a growing, singularly-linked list data structure that inherits InterfaceTraversable.</summary>
 134/// <typeparam name="T">The type of objects to be placed in the list.</typeparam>
 135public class ListLinked<T> : IList<T>, ICloneable<ListLinked<T>>
 136{
 137  internal int _count;
 138  internal Node? _head;
 139  internal Node? _tail;
 140
 141  #region Nested Types
 142
 143  internal class Node
 144  {
 145    internal T Value;
 146    internal Node? Next;
 147
 148    internal Node(T value, Node? next = null)
 149    {
 150      Value = value;
 151      Next = next;
 152    }
 153  }
 154
 155  #endregion
 156
 157  #region Constructors
 158
 159  internal ListLinked(ListLinked<T> list)
 160  {
 161    if (list._head is not null)
 162    {
 163      _head = new Node(value: list._head.Value);
 164      Node? a = list._head.Next;
 165      Node? b = _head;
 166      while (a is not null)
 167      {
 168        b.Next = new Node(value: a.Value);
 169        b = b.Next;
 170        a = a.Next;
 171      }
 172      _tail = b;
 173      _count = list._count;
 174    }
 175  }
 176
 177  /// <summary>Creates an instance of a <see cref="ListLinked{T}"/>.<br/></summary>
 178  public ListLinked()
 179  {
 180    _head = _tail = null;
 181    _count = 0;
 182  }
 183
 184  #endregion
 185
 186  #region Properties
 187
 188  /// <inheritdoc/>
 189  public int Count => _count;
 190
 191  #endregion
 192
 193  #region Methods
 194
 195  /// <inheritdoc/>
 196  public (bool Success, Exception? Exception) TryAdd(T value)
 197  {
 198    if (_tail is null)
 199    {
 200      _head = _tail = new Node(value: value);
 201    }
 202    else
 203    {
 204      _tail = _tail.Next = new Node(value: value);
 205    }
 206    _count++;
 207    return (true, null);
 208  }
 209
 210  /// <inheritdoc/>
 211  public void Clear()
 212  {
 213    _head = null;
 214    _tail = null;
 215    _count = 0;
 216  }
 217
 218  /// <inheritdoc/>
 219  public ListLinked<T> Clone() => new(this);
 220
 221  /// <summary>Removes the first equality by object reference.</summary>
 222  /// <param name="predicate">The predicate to determine removal.</param>
 223  public void RemoveFirst(Func<T, bool> predicate)
 224  {
 225    if (!TryRemoveFirst(predicate, out Exception? exception))
 226    {
 227      throw exception ?? new TowelBugException($"{nameof(TryRemoveFirst)} failed but the {nameof(exception)} is null");
 228    }
 229  }
 230
 231  /// <summary>Removes all predicated items from the list.</summary>
 232  /// <typeparam name="TPredicate">The type of predicate to determine removal.</typeparam>
 233  /// <param name="predicate">The predicate to determine removal.</param>
 234  public void RemoveAll<TPredicate>(TPredicate predicate = default)
 235    where TPredicate : struct, IFunc<T, bool>
 236  {
 237    if (_head is not null)
 238    {
 239      while (predicate.Invoke(_head!.Value))
 240      {
 241        _head = _head.Next;
 242        _count--;
 243      }
 244      Node? tail = null;
 245      for (Node? node = _head; node!.Next is not null; node = node.Next)
 246      {
 247        if (predicate.Invoke(node.Next.Value))
 248        {
 249          if (node.Next.Equals(_tail))
 250          {
 251            _tail = node;
 252          }
 253          node.Next = node.Next.Next;
 254          _count--;
 255        }
 256        else
 257        {
 258          tail = node;
 259        }
 260      }
 261      _tail = tail;
 262    }
 263  }
 264
 265  /// <summary>Tries to remove the first predicated value if the value exists.</summary>
 266  /// <param name="predicate">The predicate to determine removal.</param>
 267  /// <returns>True if the value was removed. False if the value did not exist.</returns>
 268  public bool TryRemoveFirst(Func<T, bool> predicate) =>
 269    TryRemoveFirst(predicate, out _);
 270
 271  /// <summary>Tries to remove the first predicated value if the value exists.</summary>
 272  /// <param name="predicate">The predicate to determine removal.</param>
 273  /// <param name="exception">The exception that occurred if the remove failed.</param>
 274  /// <returns>True if the value was removed. False if the value did not exist.</returns>
 275  public bool TryRemoveFirst(Func<T, bool> predicate, out Exception? exception) =>
 276    TryRemoveFirst<SFunc<T, bool>>(out exception, predicate);
 277
 278  /// <summary>Tries to remove the first predicated value if the value exists.</summary>
 279  /// <typeparam name="TPredicate">The type of predicate to determine removal.</typeparam>
 280  /// <param name="exception">The exception that occurred if the remove failed.</param>
 281  /// <param name="predicate">The predicate to determine removal.</param>
 282  /// <returns>True if the value was removed. False if the value did not exist.</returns>
 283  public bool TryRemoveFirst<TPredicate>(out Exception? exception, TPredicate predicate = default)
 284    where TPredicate : struct, IFunc<T, bool>
 285  {
 286    for (Node? node = _head, previous = null; node is not null; previous = node, node = node.Next)
 287    {
 288      if (predicate.Invoke(node.Value))
 289      {
 290        if (previous is null)
 291        {
 292          _head = node.Next;
 293        }
 294        else
 295        {
 296          previous.Next = node.Next;
 297        }
 298        _count--;
 299        exception = null;
 300        return true;
 301      }
 302    }
 303    exception = new ArgumentException("Attempting to remove a non-existing value from a list.");
 304    return false;
 305  }
 306
 307  /// <inheritdoc/>
 308  public StepStatus StepperBreak<TStep>(TStep step = default)
 309    where TStep : struct, IFunc<T, StepStatus>
 310  {
 311    for (Node? node = _head; node is not null; node = node.Next)
 312    {
 313      T temp = node.Value;
 314      if (step.Invoke(temp) is Break)
 315      {
 316        node.Value = temp;
 317        return Break;
 318      }
 319      node.Value = temp;
 320    }
 321    return Continue;
 322  }
 323
 324  System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 325
 326  /// <inheritdoc/>
 327  public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 328  {
 329    for (Node? node = _head; node is not null; node = node.Next)
 330    {
 331      yield return node.Value;
 332    }
 333  }
 334
 335  /// <inheritdoc/>
 336  public T[] ToArray()
 337  {
 338    if (_count is 0)
 339    {
 340      return Array.Empty<T>();
 341    }
 342    T[] array = new T[_count];
 343    for (var (i, node) = (0, _head); node is not null; node = node.Next, i++)
 344    {
 345      array[i] = node.Value;
 346    }
 347    return array;
 348  }
 349
 350  #endregion
 351}
 352
 353/// <summary>A list implemented as a growing array.</summary>
 354/// <typeparam name="T">The type of objects to be placed in the list.</typeparam>
 355public class ListArray<T> : IList<T>, ICloneable<ListArray<T>>
 356{
 357  internal T[] _array;
 358  internal int _count;
 359
 360  #region Constructor
 361
 362  /// <summary>Creates an instance of a <see cref="ListArray{T}"/>.</summary>
 234363  public ListArray() : this(1) { }
 364
 365  /// <summary>
 366  /// Creates an instance of a ListArray, and sets it's minimum capacity.<br/>
 367  /// Runtime: O(1)
 368  /// </summary>
 369  /// <param name="expectedCount">The initial and smallest array size allowed by this list.</param>
 78370  public ListArray(int expectedCount)
 78371  {
 78372    if (expectedCount < 1)
 0373    {
 0374      throw new ArgumentOutOfRangeException(nameof(expectedCount), expectedCount, $"{nameof(expectedCount)} < 1");
 375    }
 78376    _array = new T[expectedCount];
 78377    _count = 0;
 78378  }
 379
 0380  internal ListArray(ListArray<T> list)
 0381  {
 0382    _array = (T[])list._array.Clone();
 0383    _count = list._count;
 0384  }
 385
 0386  internal ListArray(T[] array, int count)
 0387  {
 0388    _array = array;
 0389    _count = count;
 0390  }
 391
 392  #endregion
 393
 394  #region Properties
 395
 396  /// <summary>Look-up and set an indexed item in the list.</summary>
 397  /// <param name="index">The index of the item to get or set.</param>
 398  /// <returns>The value at the given index.</returns>
 399  public T this[int index]
 400  {
 401    get
 34402    {
 34403      if (index < 0 || index > _count)
 0404      {
 0405        throw new ArgumentOutOfRangeException(nameof(index), index, $"{nameof(index)}[{index}] < 0 || {nameof(index)}[{i
 406      }
 34407      return _array[index];
 34408    }
 409    set
 0410    {
 0411      if (index < 0 || index > _count)
 0412      {
 0413        throw new ArgumentOutOfRangeException(nameof(index), index, $"{nameof(index)}[{index}] < 0 || {nameof(index)}[{i
 414      }
 0415      _array[index] = value;
 0416    }
 417  }
 418
 419  /// <inheritdoc/>
 1140420  public int Count => _count;
 421
 422  /// <summary>
 423  /// Gets the current capacity of the list.<br/>
 424  /// Runtime: O(1)
 425  /// </summary>
 0426  public int CurrentCapacity => _array.Length;
 427
 428  #endregion
 429
 430  #region Methods
 431
 432  /// <inheritdoc/>
 433  public (bool Success, Exception? Exception) TryAdd(T value)
 1290434  {
 1290435    if (_count == _array.Length)
 156436    {
 156437      if (_array.Length > int.MaxValue / 2)
 0438      {
 0439        return (false, new InvalidOperationException($"{nameof(Count)} == {nameof(CurrentCapacity)} && {nameof(CurrentCa
 440      }
 156441      Array.Resize<T>(ref _array, _array.Length * 2);
 156442    }
 1290443    _array[_count++] = value;
 1290444    return (true, null);
 1290445  }
 446
 447  /// <summary>Adds an item at a given index.</summary>
 448  /// <param name="addition">The item to be added.</param>
 449  /// <param name="index">The index to add the item at.</param>
 450  /// <exception cref="ArgumentOutOfRangeException">index &lt; 0 || index &gt; <see cref="CurrentCapacity"/></exception>
 451  /// <exception cref="InvalidOperationException"><see cref="Count"/> == <see cref="CurrentCapacity"/> &amp;&amp; <see c
 452  public void Add(T addition, int index)
 0453  {
 0454    if (index < 0 || index > _array.Length)
 0455    {
 0456      throw new ArgumentOutOfRangeException(nameof(index), index, $"{nameof(index)} < 0 || {nameof(index)} > {nameof(Cou
 457    }
 0458    if (_count == _array.Length)
 0459    {
 0460      if (_array.Length > int.MaxValue / 2)
 0461      {
 0462        throw new InvalidOperationException($"{nameof(Count)} == {nameof(CurrentCapacity)} && {nameof(CurrentCapacity)} 
 463      }
 0464      Array.Resize<T>(ref _array, _array.Length * 2);
 0465    }
 0466    for (int i = _count; i > index; i--)
 0467    {
 0468      _array[i] = _array[i - 1];
 0469    }
 0470    _array[index] = addition;
 0471    _count++;
 0472  }
 473
 474  /// <inheritdoc/>
 475  public void Clear()
 0476  {
 0477    _array = new T[1];
 0478    _count = 0;
 0479  }
 480
 481  /// <inheritdoc/>
 0482  public ListArray<T> Clone() => new(this);
 483
 484  /// <summary>
 485  /// Removes the item at a specific index.<br/>
 486  /// Runtime: O(n), Ω(n - index), ε(n - index)
 487  /// </summary>
 488  /// <param name="index">The index of the item to be removed.</param>
 489  public void Remove(int index)
 468490  {
 468491    RemoveWithoutShrink(index);
 468492    if (_count < _array.Length / 2)
 28493    {
 28494      Array.Resize<T>(ref _array, _array.Length / 2);
 28495    }
 468496  }
 497
 498  /// <summary>
 499  /// Removes the item at a specific index.<br/>
 500  /// Runtime: Θ(n - index)
 501  /// </summary>
 502  /// <param name="index">The index of the item to be removed.</param>
 503  /// <exception cref="ArgumentOutOfRangeException">Thrown when: index &lt; 0 || index &gt;= _count</exception>
 504  public void RemoveWithoutShrink(int index)
 468505  {
 468506    if (index < 0 || index >= _count)
 0507    {
 0508      throw new ArgumentOutOfRangeException(nameof(index), index, $"{nameof(index)} < 0 || {nameof(index)} >= {nameof(Co
 509    }
 27468510    for (int i = index; i < _count - 1; i++)
 13266511    {
 13266512      _array[i] = _array[i + 1];
 13266513    }
 468514    _count--;
 468515  }
 516
 517  /// <summary>
 518  /// Removes all predicated items from the list.<br/>
 519  /// Runtime: Θ(n)
 520  /// </summary>
 521  /// <typeparam name="TPredicate">The type of predicate to determine removal.</typeparam>
 522  /// <param name="predicate">The predicate to determine removals.</param>
 523  public void RemoveAll<TPredicate>(TPredicate predicate = default)
 524    where TPredicate : struct, IFunc<T, bool>
 2525  {
 2526    RemoveAllWithoutShrink(predicate);
 2527    if (_count < _array.Length / 2)
 0528    {
 0529      Array.Resize<T>(ref _array, _array.Length / 2);
 0530    }
 2531  }
 532
 533  /// <summary>
 534  /// Removes all predicated items from the list.<br/>
 535  /// Runtime: Θ(n)
 536  /// </summary>
 537  /// <typeparam name="TPredicate">The type of predicate to determine removal.</typeparam>
 538  /// <param name="predicate">The predicate to determine removals.</param>
 539  public void RemoveAllWithoutShrink<TPredicate>(TPredicate predicate = default)
 540    where TPredicate : struct, IFunc<T, bool>
 2541  {
 2542    if (_count is 0)
 0543    {
 0544      return;
 545    }
 2546    int removed = 0;
 404547    for (int i = 0; i < _count; i++)
 200548    {
 200549      if (predicate.Invoke(_array[i]))
 26550      {
 26551        removed++;
 26552      }
 553      else
 174554      {
 174555        _array[i - removed] = _array[i];
 174556      }
 200557    }
 2558    _count -= removed;
 2559  }
 560
 561  /// <summary>
 562  /// Removes the first predicated value from the list.<br/>
 563  /// Runtime: O(n), Ω(1)
 564  /// </summary>
 565  /// <param name="predicate">The predicate to determine removals.</param>
 566  /// <exception cref="ArgumentException">Thrown when <paramref name="predicate"/> does not find a <typeparamref name="T
 567  public void RemoveFirst(Func<T, bool> predicate)
 0568  {
 0569    if (!TryRemoveFirst(predicate, out Exception? exception))
 0570    {
 0571      throw exception ?? new TowelBugException($"{nameof(TryRemoveFirst)} failed but the {nameof(exception)} is null");
 572    }
 0573  }
 574
 575  /// <summary>
 576  /// Removes the first occurence of a value from the list without causing the list to shrink.<br/>
 577  /// Runtime: O(n), Ω(1)
 578  /// </summary>
 579  /// <param name="value">The value to remove.</param>
 580  /// <param name="equate">The delegate providing the equality check.</param>
 581  /// <exception cref="ArgumentException">Thrown when <paramref name="value"/> is not found in the list.</exception>
 582  public void RemoveFirstWithoutShrink(T value, Func<T, T, bool>? equate = null)
 0583  {
 0584    equate ??= Equate;
 0585    RemoveFirstWithoutShrink(x => equate(x, value));
 0586  }
 587
 588  /// <summary>
 589  /// Removes the first predicated value from the list wihtout shrinking the list.<br/>
 590  /// Runtime: O(n), Ω(1)
 591  /// </summary>
 592  /// <param name="predicate">The predicate to determine removals.</param>
 593  /// <exception cref="ArgumentException">Thrown when <paramref name="predicate"/> does not find a <typeparamref name="T
 594  public void RemoveFirstWithoutShrink(Func<T, bool> predicate)
 0595  {
 0596    if (!TryRemoveFirst(predicate, out Exception? exception))
 0597    {
 0598      throw exception ?? new TowelBugException($"{nameof(TryRemoveFirst)} failed but the {nameof(exception)} is null");
 599    }
 0600  }
 601
 602  /// <summary>Tries to remove the first predicated value if the value exists.</summary>
 603  /// <param name="predicate">The predicate to determine removals.</param>
 604  /// <param name="exception">The exception that occured if the removal failed.</param>
 605  /// <returns>True if the item was found and removed. False if not.</returns>
 606  public bool TryRemoveFirst(Func<T, bool> predicate, out Exception? exception) =>
 0607    TryRemoveFirst<SFunc<T, bool>>(out exception, predicate);
 608
 609  /// <summary>Tries to remove the first predicated value if the value exists.</summary>
 610  /// <typeparam name="TPredicate">The type of predicate to determine removal.</typeparam>
 611  /// <param name="exception">The exception that occurred if the remove failed.</param>
 612  /// <param name="predicate">The predicate to determine removal.</param>
 613  /// <returns>True if the value was removed. False if the value did not exist.</returns>
 614  public bool TryRemoveFirst<TPredicate>(out Exception? exception, TPredicate predicate = default)
 615    where TPredicate : struct, IFunc<T, bool>
 472616  {
 617    int i;
 25272618    for (i = 0; i < _count; i++)
 12632619    {
 12632620      if (predicate.Invoke(_array[i]))
 468621      {
 468622        Remove(i);
 468623        exception = null;
 468624        return true;
 625      }
 12164626    }
 4627    exception = new ArgumentException("Attempting to remove a non-existing item from this list.");
 4628    return false;
 472629  }
 630
 631  /// <inheritdoc/>
 632  public StepStatus StepperBreak<TStep>(TStep step = default)
 633    where TStep : struct, IFunc<T, StepStatus> =>
 1488634    _array.StepperBreak(0, _count, step);
 635
 0636  System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
 637
 638  /// <summary>Gets the enumerator for the data structure.</summary>
 639  /// <returns>The enumerator for the data structure.</returns>
 640  public System.Collections.Generic.IEnumerator<T> GetEnumerator()
 7641  {
 788642    for (int i = 0; i < _count; i++)
 387643    {
 387644      yield return _array[i];
 387645    }
 7646  }
 647
 648  /// <inheritdoc/>
 31649  public T[] ToArray() => _count is 0 ? Array.Empty<T>() : _array[.._count];
 650
 651  /// <summary>Resizes this allocation to the current count.</summary>
 0652  public void Trim() => _array = _count is 0 ? new T[1] : _array[.._count];
 653
 654  #endregion
 655}