Skip to content

Commit a256324

Browse files
committed
Add new EnumerableExtensions methods and update documentation
1 parent 3e3e32b commit a256324

8 files changed

Lines changed: 134 additions & 120 deletions

File tree

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
namespace DotNetExtensions.Collections;
2+
3+
public static partial class EnumerableExtensions
4+
{
5+
/// <summary>
6+
/// Returns all overlapping subarrays of the specified length from the source sequence.
7+
/// </summary>
8+
/// <typeparam name="T">The type of elements in the source sequence.</typeparam>
9+
/// <param name="source">The source sequence.</param>
10+
/// <param name="length">The length of each subarray.</param>
11+
/// <returns>
12+
/// A sequence of subarrays with the specified length,
13+
/// each represented as an array of type <typeparamref name="T"/>.
14+
/// </returns>
15+
/// <exception cref="ArgumentNullException">
16+
/// Thrown if the <paramref name="source"/> is <c>null</c>.
17+
/// </exception>
18+
/// <exception cref="ArgumentOutOfRangeException">
19+
/// Thrown if the <paramref name="length"/> is negative.
20+
/// </exception>
21+
public static IEnumerable<T[]> Adjacent<T>(this IEnumerable<T> source, int length)
22+
{
23+
ArgumentNullException.ThrowIfNull(source);
24+
ArgumentOutOfRangeException.ThrowIfNegative(length);
25+
26+
return AdjacentInternal(source, length);
27+
}
28+
29+
private static IEnumerable<T[]> AdjacentInternal<T>(IEnumerable<T> source, int length)
30+
{
31+
var array = source as T[] ?? source.ToArray();
32+
if (length > array.Length)
33+
yield break;
34+
35+
for (var i = 0; i <= array.Length - length; i++)
36+
{
37+
var segment = new T[length];
38+
Array.Copy(array, i, segment, 0, length);
39+
yield return segment;
40+
}
41+
}
42+
}

DotNetExtensions/Collections/Combinations.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,33 +9,33 @@ public static partial class EnumerableExtensions
99
/// <param name="source">The sequence of elements to choose combinations from.</param>
1010
/// <param name="length">The length of each combination.</param>
1111
/// <returns>
12-
/// A sequence of combinations, where each combination is represented as an <see cref="IEnumerable{T}"/>.
12+
/// A sequence of combinations, where each combination is represented as a <see cref="List{T}"/>.
1313
/// </returns>
1414
/// <exception cref="ArgumentNullException">
1515
/// Thrown if the <paramref name="source"/> is <c>null</c>.
1616
/// </exception>
1717
/// <exception cref="ArgumentOutOfRangeException">
1818
/// Thrown if the <paramref name="length"/> is negative.
1919
/// </exception>
20-
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> source, int length)
20+
public static IEnumerable<List<T>> Combinations<T>(this IEnumerable<T> source, int length)
2121
{
2222
ArgumentNullException.ThrowIfNull(source);
2323
ArgumentOutOfRangeException.ThrowIfNegative(length);
2424

2525
return CombinationsInternal(source, length);
2626
}
2727

28-
private static IEnumerable<IEnumerable<T>> CombinationsInternal<T>(IEnumerable<T> source, int length)
28+
private static IEnumerable<List<T>> CombinationsInternal<T>(IEnumerable<T> source, int length)
2929
{
30-
var array = source as T[] ?? source.ToArray();
30+
var array = source as IList<T> ?? source.ToArray();
3131

3232
if (length == 0)
3333
{
3434
yield return [];
3535
yield break;
3636
}
3737

38-
if (length > array.Length)
38+
if (length > array.Count)
3939
yield break;
4040

4141
// Stack to hold the current state for iteration
@@ -53,8 +53,8 @@ private static IEnumerable<IEnumerable<T>> CombinationsInternal<T>(IEnumerable<T
5353
continue;
5454
}
5555

56-
// Push next elements onto the stack in reverse order to ensure correct order
57-
for (var i = array.Length - 1; i > index; i--)
56+
// Push next elements onto the stack in reverse order to ensure the correct order
57+
for (var i = array.Count - 1; i > index; i--)
5858
{
5959
var newCombination = new List<T>(combination) { array[i] };
6060
stack.Push((i, newCombination));
Lines changed: 2 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,6 @@
1-
namespace DotNetExtensions.Collections;
1+
namespace DotNetExtensions.Collections;
22

33
/// <summary>
44
/// Provides extension methods for working with enumerable sequences.
55
/// </summary>
6-
public static partial class EnumerableExtensions
7-
{
8-
/// <summary>
9-
/// Returns a sequence of consecutive pairs of elements from the source sequence.
10-
/// </summary>
11-
/// <typeparam name="T">The type of elements in the source sequence.</typeparam>
12-
/// <param name="source">The source sequence.</param>
13-
/// <returns>
14-
/// A sequence of tuples containing consecutive pairs of elements from the source.
15-
/// </returns>
16-
/// <exception cref="ArgumentNullException">
17-
/// Thrown if the <paramref name="source"/> is <c>null</c>.
18-
/// </exception>
19-
public static IEnumerable<(T First, T Second)> Pairwise<T>(this IEnumerable<T> source)
20-
{
21-
ArgumentNullException.ThrowIfNull(source);
22-
23-
return PairwiseInternal(source);
24-
}
25-
26-
private static IEnumerable<(T First, T Second)> PairwiseInternal<T>(IEnumerable<T> source)
27-
{
28-
using var enumerator = source.GetEnumerator();
29-
30-
// Buffer the first element
31-
if (!enumerator.MoveNext()) yield break;
32-
var previous = enumerator.Current;
33-
34-
while (enumerator.MoveNext())
35-
{
36-
var current = enumerator.Current;
37-
yield return (previous, current);
38-
previous = current;
39-
}
40-
}
41-
42-
/// <summary>
43-
/// Returns all overlapping sub-arrays of the specified length from the source sequence.
44-
/// </summary>
45-
/// <typeparam name="T">The type of elements in the source sequence.</typeparam>
46-
/// <param name="source">The source sequence.</param>
47-
/// <param name="length">The length of each subarray.</param>
48-
/// <returns>
49-
/// A sequence of sub-arrays of the specified length, each represented as an array of type <typeparamref name="T"/>.
50-
/// </returns>
51-
/// <exception cref="ArgumentNullException">
52-
/// Thrown if the <paramref name="source"/> is <c>null</c>.
53-
/// </exception>
54-
/// <exception cref="ArgumentOutOfRangeException">
55-
/// Thrown if the <paramref name="length"/> is negative.
56-
/// </exception>
57-
public static IEnumerable<T[]> Adjacent<T>(this IEnumerable<T> source, int length)
58-
{
59-
ArgumentNullException.ThrowIfNull(source);
60-
ArgumentOutOfRangeException.ThrowIfNegative(length);
61-
62-
return AdjacentInternal(source, length);
63-
}
64-
65-
private static IEnumerable<T[]> AdjacentInternal<T>(IEnumerable<T> source, int length)
66-
{
67-
var array = source as T[] ?? source.ToArray();
68-
if (length > array.Length)
69-
yield break;
70-
71-
for (var i = 0; i <= array.Length - length; i++)
72-
{
73-
var segment = new T[length];
74-
Array.Copy(array, i, segment, 0, length);
75-
yield return segment;
76-
}
77-
}
78-
79-
/// <summary>
80-
/// Returns a new sequence that skips the element at the specified index.
81-
/// </summary>
82-
/// <typeparam name="T">The type of elements in the source sequence.</typeparam>
83-
/// <param name="source">The source sequence.</param>
84-
/// <param name="index">The index of the element to skip.</param>
85-
/// <returns>
86-
/// A new sequence without the element at the specified index.
87-
/// </returns>
88-
/// <exception cref="ArgumentNullException">
89-
/// Thrown if the <paramref name="source"/> is <c>null</c>.
90-
/// </exception>
91-
/// <exception cref="ArgumentOutOfRangeException">
92-
/// Thrown if the <paramref name="index"/> is negative.
93-
/// </exception>
94-
public static IEnumerable<T> SkipAt<T>(this IEnumerable<T> source, int index)
95-
{
96-
ArgumentNullException.ThrowIfNull(source);
97-
ArgumentOutOfRangeException.ThrowIfNegative(index);
98-
99-
return SkipAtInternal(source, index);
100-
}
101-
102-
private static IEnumerable<T> SkipAtInternal<T>(IEnumerable<T> source, int index)
103-
{
104-
using var enumerator = source.GetEnumerator();
105-
var i = 0;
106-
107-
while (enumerator.MoveNext())
108-
{
109-
if (i++ == index) continue;
110-
yield return enumerator.Current;
111-
}
112-
}
113-
}
6+
public static partial class EnumerableExtensions;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
namespace DotNetExtensions.Collections;
2+
3+
public static partial class EnumerableExtensions
4+
{
5+
/// <summary>
6+
/// Returns a sequence of consecutive pairs of elements from the source sequence.
7+
/// </summary>
8+
/// <typeparam name="T">The type of elements in the source sequence.</typeparam>
9+
/// <param name="source">The source sequence.</param>
10+
/// <returns>
11+
/// A sequence of tuples containing consecutive pairs of elements from the source.
12+
/// </returns>
13+
/// <exception cref="ArgumentNullException">
14+
/// Thrown if the <paramref name="source"/> is <c>null</c>.
15+
/// </exception>
16+
public static IEnumerable<(T First, T Second)> Pairwise<T>(this IEnumerable<T> source)
17+
{
18+
ArgumentNullException.ThrowIfNull(source);
19+
20+
return PairwiseInternal(source);
21+
}
22+
23+
private static IEnumerable<(T First, T Second)> PairwiseInternal<T>(IEnumerable<T> source)
24+
{
25+
using var enumerator = source.GetEnumerator();
26+
27+
// Buffer the first element
28+
if (!enumerator.MoveNext()) yield break;
29+
var previous = enumerator.Current;
30+
31+
while (enumerator.MoveNext())
32+
{
33+
var current = enumerator.Current;
34+
yield return (previous, current);
35+
previous = current;
36+
}
37+
}
38+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
namespace DotNetExtensions.Collections;
2+
3+
public static partial class EnumerableExtensions
4+
{
5+
/// <summary>
6+
/// Returns a new sequence that skips the element at the specified index.
7+
/// </summary>
8+
/// <typeparam name="T">The type of elements in the source sequence.</typeparam>
9+
/// <param name="source">The source sequence.</param>
10+
/// <param name="index">The index of the element to skip.</param>
11+
/// <returns>
12+
/// A new sequence without the element at the specified index.
13+
/// </returns>
14+
/// <exception cref="ArgumentNullException">
15+
/// Thrown if the <paramref name="source"/> is <c>null</c>.
16+
/// </exception>
17+
/// <exception cref="ArgumentOutOfRangeException">
18+
/// Thrown if the <paramref name="index"/> is negative.
19+
/// </exception>
20+
public static IEnumerable<T> SkipAt<T>(this IEnumerable<T> source, int index)
21+
{
22+
ArgumentNullException.ThrowIfNull(source);
23+
ArgumentOutOfRangeException.ThrowIfNegative(index);
24+
25+
return SkipAtInternal(source, index);
26+
}
27+
28+
private static IEnumerable<T> SkipAtInternal<T>(IEnumerable<T> source, int index)
29+
{
30+
using var enumerator = source.GetEnumerator();
31+
var i = 0;
32+
33+
while (enumerator.MoveNext())
34+
{
35+
if (i++ == index) continue;
36+
yield return enumerator.Current;
37+
}
38+
}
39+
}

DotNetExtensions/Core/PointExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ public static (Point Left, Point Right, Point Top, Point Bottom) GetNeighbors(th
3636
/// <param name="other">The target point.</param>
3737
/// <returns>The Manhattan distance between the two points.</returns>
3838
/// <remarks>
39-
/// The Manhattan distance is the sum of the absolute differences of their X and Y coordinates.
39+
/// The Manhattan distance is calculated
40+
/// by summing the absolute differences between the X coordinates and the Y coordinates.
4041
/// It is commonly used in grid-based distance calculations where diagonal movement is not allowed.
4142
/// </remarks>
4243
public static int ManhattanDistance(this Point point, Point other)

DotNetExtensions/DotNetExtensions.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
<TargetFramework>net9.0</TargetFramework>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
7-
8-
<Version>5.1.0</Version>
7+
8+
<Version>5.2.0</Version>
99
<Authors>Diogo Medeiros</Authors>
1010
<Company>Diogo Medeiros</Company>
1111
<Description>This is a collection of extension methods for .NET Core.</Description>
@@ -18,4 +18,5 @@
1818
<ItemGroup>
1919
<None Include="..\README.md" Pack="true" PackagePath="\"/>
2020
</ItemGroup>
21+
2122
</Project>

DotNetExtensions/Utilities/Accumulator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace DotNetExtensions.Utilities;
44

55
/// <summary>
6-
/// A generic accumulator class that tracks the minimum, maximum, sum, and count of added values,
6+
/// A generic accumulator class that tracks the minimum, maximum, sum, and count of added values
77
/// and calculates the mean of the values.
88
/// </summary>
99
/// <typeparam name="T">

0 commit comments

Comments
 (0)