< Summary

Information
Class: SwiftCollections.SwiftExtensions
Assembly: SwiftCollections
File(s): /home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Extensions/SwiftExtensions.cs
Line coverage
100%
Covered lines: 56
Uncovered lines: 0
Coverable lines: 56
Total lines: 222
Line coverage: 100%
Branch coverage
100%
Covered branches: 28
Total branches: 28
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Populate(...)100%22100%
Populate(...)100%22100%
Populate(...)100%22100%
TryIndex(...)100%88100%
Shuffle()100%22100%
ShuffleInPlace(...)100%22100%
IsPopulated(...)100%11100%
IsPopulatedSafe(...)100%22100%
FromEnd(...)100%22100%
FromEnd(...)100%22100%
PopLast(...)100%11100%
SkipFromEnd()100%44100%
SecondToLast(...)100%11100%

File(s)

/home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Extensions/SwiftExtensions.cs

#LineLine coverage
 1//=======================================================================
 2// SwiftExtensions.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using SwiftCollections.Diagnostics;
 9using System;
 10using System.Collections.Generic;
 11using System.Runtime.CompilerServices;
 12
 13namespace SwiftCollections;
 14
 15/// <summary>
 16/// Provides extension methods for collection manipulation and utility functions.
 17/// </summary>
 18public static class SwiftExtensions
 19{
 20    /// <summary>
 21    /// Populates an array with values generated by a specified provider function.
 22    /// </summary>
 23    /// <typeparam name="T">The type of the elements in the array.</typeparam>
 24    /// <param name="array">The array to populate.</param>
 25    /// <param name="provider">A function that generates a value for each element in the array.</param>
 26    /// <returns>The populated array.</returns>
 27    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 28    public static T[] Populate<T>(this T[] array, Func<T> provider)
 29    {
 39656630        for (int i = 0; i < array.Length; i++)
 19809331            array[i] = provider();
 19032        return array;
 33    }
 34
 35    /// <summary>
 36    /// Populates an array with values generated by a provider function that accepts the current index.
 37    /// </summary>
 38    /// <typeparam name="T">The type of the elements in the array.</typeparam>
 39    /// <param name="array">The array to populate.</param>
 40    /// <param name="provider">A function that generates a value for each element based on its index.</param>
 41    /// <returns>The populated array.</returns>
 42    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 43    public static T[] Populate<T>(this T[] array, Func<int, T> provider)
 44    {
 845        for (int i = 0; i < array.Length; i++)
 346            array[i] = provider(i);
 147        return array;
 48    }
 49
 50    /// <summary>
 51    /// Populates an array with new instances of the specified type.
 52    /// The type must have a parameterless constructor.
 53    /// </summary>
 54    /// <typeparam name="T">The type of the elements in the array.</typeparam>
 55    /// <param name="array">The array to populate.</param>
 56    /// <returns>The populated array.</returns>
 57    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 58    public static T[] Populate<T>(this T[] array) where T : new()
 59    {
 660        for (int i = 0; i < array.Length; i++)
 261            array[i] = new T();
 162        return array;
 63    }
 64
 65    /// <summary>
 66    /// Attempts to retrieve an element from the array at the specified index.
 67    /// Returns true if the index is valid and the element is retrieved; otherwise, returns false.
 68    /// </summary>
 69    /// <typeparam name="T">The type of elements in the array.</typeparam>
 70    /// <param name="array">The array from which to retrieve the element.</param>
 71    /// <param name="index">The index of the element to retrieve.</param>
 72    /// <param name="result">
 73    /// When this method returns, contains the element at the specified index if the index is valid;
 74    /// otherwise, the default value for the type of the element.
 75    /// </param>
 76    /// <returns>
 77    /// True if the element at the specified index was retrieved successfully; otherwise, false.
 78    /// </returns>
 79    public static bool TryIndex<T>(this T[] array, int index, out T result)
 80    {
 581        if (array != null)
 82        {
 483            if (index < 0)
 84            {
 85                // Support negative indices to access elements from the end
 286                index = array.Length + index;
 87            }
 488            if (index >= 0 && index < array.Length)
 89            {
 290                result = array[index];
 291                return true;
 92            }
 93        }
 94
 395        result = default!;
 396        return false;
 97    }
 98
 99    /// <summary>
 100    /// An iterator that yields the elements of the source collection in a random order using the specified random numbe
 101    /// </summary>
 102    /// <typeparam name="T">The type of elements in the collection.</typeparam>
 103    /// <param name="source">The collection to shuffle.</param>
 104    /// <param name="rng">The random number generator to use for shuffling.</param>
 105    /// <returns>An iterator that yields the shuffled elements.</returns>
 106    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
 107    {
 3108        SwiftThrowHelper.ThrowIfNull(source, nameof(source));
 2109        SwiftThrowHelper.ThrowIfNull(rng, nameof(rng));
 110
 1111        SwiftList<T> buffer = new(source);
 1112        int n = buffer.Count;
 7113        while (n > 0)
 114        {
 6115            int k = rng.Next(n);
 6116            n--;
 117            // Swap the selected element with the last unshuffled element
 6118            (buffer[k], buffer[n]) = (buffer[n], buffer[k]);
 6119            yield return buffer[n];
 120        }
 1121    }
 122
 123    /// <summary>
 124    /// Shuffles the elements of the list in place using the specified random number generator.
 125    /// </summary>
 126    /// <typeparam name="T">The type of elements in the list.</typeparam>
 127    /// <param name="list">The list to shuffle.</param>
 128    /// <param name="rng">The random number generator to use for shuffling.</param>
 129    public static void ShuffleInPlace<T>(this IList<T> list, Random rng)
 130    {
 3131        SwiftThrowHelper.ThrowIfNull(list, nameof(list));
 2132        SwiftThrowHelper.ThrowIfNull(rng, nameof(rng));
 133
 1134        int n = list.Count;
 6135        while (n > 1)
 136        {
 5137            n--;
 5138            int k = rng.Next(n + 1);
 5139            (list[n], list[k]) = (list[k], list[n]);
 140        }
 1141    }
 142
 143    /// <summary>
 144    /// Determines whether a sequence contains any elements.
 145    /// </summary>
 146    /// <typeparam name="T"></typeparam>
 147    /// <param name="source"> The <see cref="IEnumerable{T}"/> to check for emptiness.</param>
 148    /// <returns>
 149    /// true if the source sequence contains any elements; otherwise, false.
 150    /// </returns>
 151    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 152    public static bool IsPopulated<T>(this IEnumerable<T> source)
 153    {
 4154        SwiftThrowHelper.ThrowIfNull(source, nameof(source));
 3155        using IEnumerator<T> enumerator = source.GetEnumerator();
 3156        return enumerator.MoveNext();
 3157    }
 158
 159    /// <summary>
 160    /// Determines whether the collection is not null and contains any elements.
 161    /// </summary>
 162    /// <typeparam name="T">The type of elements in the collection.</typeparam>
 163    /// <param name="source">The collection to check.</param>
 164    /// <returns>
 165    /// True if the collection is not null and contains at least one element; otherwise, false.
 166    /// </returns>
 167    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2168    public static bool IsPopulatedSafe<T>(this IEnumerable<T> source) => source != null && source.IsPopulated();
 169
 170    /// <summary>
 171    /// Gets the element at the specified index from the end (1-based).
 172    /// For example, FromEnd(1) returns the last item, FromEnd(2) returns second-to-last.
 173    /// </summary>
 174    public static T FromEnd<T>(this IEnumerable<T> source, int reverseIndex)
 175    {
 4176        if (source is SwiftList<T> swift)
 1177            return swift.FromEnd(reverseIndex);
 178
 179        // fallback for generic IEnumerable
 3180        var buffer = new SwiftList<T>(source);
 3181        return buffer.FromEnd(reverseIndex);
 182    }
 183
 184    /// <summary>
 185    /// Gets the element at the specified index from the end (1-based) from SwiftList.
 186    /// </summary>
 187    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 188    public static T FromEnd<T>(this SwiftList<T> list, int reverseIndex)
 189    {
 7190        SwiftThrowHelper.ThrowIfArgumentOutOfRange(reverseIndex <= 0 || reverseIndex > list.Count, reverseIndex, nameof(
 5191        return list[^reverseIndex];
 192    }
 193
 194    /// <summary>
 195    /// Returns the last item in the sequence.
 196    /// </summary>
 197    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1198    public static T PopLast<T>(this IEnumerable<T> source) => source.FromEnd(1);
 199
 200    /// <summary>
 201    /// Bypasses a specified number of elements from the end and then returns the remaining elements.
 202    /// </summary>
 203    public static IEnumerable<T> SkipFromEnd<T>(this IEnumerable<T> source, int count)
 204    {
 5205        SwiftThrowHelper.ThrowIfNull(source, nameof(source));
 4206        SwiftThrowHelper.ThrowIfNegative(count, nameof(count));
 207
 3208        SwiftQueue<T> buffer = new();
 209
 26210        foreach (T item in source)
 211        {
 10212            buffer.Enqueue(item);
 10213            if (buffer.Count > count)
 6214                yield return buffer.Dequeue();
 215        }
 3216    }
 217
 218    /// <summary>
 219    /// Returns the second-to-last item in the sequence.
 220    /// </summary>
 1221    public static T SecondToLast<T>(this IEnumerable<T> source) => source.FromEnd(2);
 222}