Skip to content

Commit

Permalink
Add Min/MaxItems (#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
viceroypenguin authored Sep 28, 2022
1 parent 7ee90f0 commit b8564b5
Show file tree
Hide file tree
Showing 7 changed files with 421 additions and 1 deletion.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,11 @@ The documentation for the SuperLinq.Async methods can be found [here](Source/Sup
| LeftJoin | ⚠️[^9] ||
| LeftOuterJoin | ✔️ | ✔️ |
| MaxBy | ❌<br/>(Removed[^8]) |[^8] |
| MaxItems | ✔️ | ✔️ |
| MaxItemsBy | ✔️ | ✔️ |
| MinBy | ❌<br/>(Removed[^8]) |[^8] |
| MinItems | ✔️ | ✔️ |
| MinItemsBy | ✔️ | ✔️ |
| Move | ✔️ | ⏱([#27](https://github.com/viceroypenguin/SuperLinq/issues/27)) |
| OrderBy | ✔️ | ✔️ |
| OrderedMerge | ⚠️[^9] ||
Expand Down Expand Up @@ -154,7 +158,7 @@ The documentation for the SuperLinq.Async methods can be found [here](Source/Sup

[^1]: Internal operator no longer used
[^2]: Backsert has been obsoleted in favor of `.Insert(Index)`
[^8]: These methods have been removed; their names conflict with the new `.MinBy()`/`.MaxBy()` in .NET 6, and their behavior is better implemented by `.PartialSort()`/`.DensePartialSort()`
[^8]: These methods have been renamed to `.MinItems()`/`.MaxItems()`; their names conflict with the new `.MinBy()`/`.MaxBy()` in .NET 6.
[^3]: Batch has been replaced by `.Buffer()` in .NET Core 3.1/.NET 5 (implemented by System.Interactive(.Async)) and `.Chunk()` in .NET 6; it is kept only for compatibility reasons.
[^4]: Pipe has been replaced by `.Do()` (implemented by System.Interactive(.Async))
[^5]: Rank has changed behavior, please review the breaking changes for Rank [here](Source/SuperLinq/readme.md#rank).
Expand Down
92 changes: 92 additions & 0 deletions Source/SuperLinq.Async/MaxItems.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
namespace SuperLinq.Async;

public static partial class AsyncSuperEnumerable
{
/// <summary>
/// Returns all of the items that share the maximum value of a sequence.
/// </summary>
/// <typeparam name="T">Type of elements in the sequence.</typeparam>
/// <param name="source">The source sequence.</param>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <remarks>
/// <para>
/// This operator is a shortcut for <see cref="DensePartialSort{T}(IAsyncEnumerable{T}, int, OrderByDirection)"/> with a
/// <c>direction</c> of <see cref="OrderByDirection.Descending"/> and a <c>count</c> of <c>1</c>.
/// </para>
/// <para>
/// This operator uses deferred execution and streams it results.
/// </para>
/// </remarks>
public static IAsyncEnumerable<T> MaxItems<T>(this IAsyncEnumerable<T> source)
{
return source.DensePartialSort(1, OrderByDirection.Descending);
}

/// <summary>
/// Returns all of the items that share the maximum value of a sequence.
/// </summary>
/// <typeparam name="T">Type of elements in the sequence.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="comparer">A <see cref="IComparer{T}"/> to compare elements.</param>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <remarks>
/// <para>
/// This operator is a shortcut for <see cref="DensePartialSort{T}(IAsyncEnumerable{T}, int, IComparer{T}?, OrderByDirection)"/> with a
/// <c>count</c> of <c>1</c>.
/// </para>
/// <para>
/// This operator uses deferred execution and streams it results.
/// </para>
/// </remarks>
public static IAsyncEnumerable<T> MaxItems<T>(this IAsyncEnumerable<T> source, IComparer<T>? comparer)
{
return source.DensePartialSort(1, comparer, OrderByDirection.Descending);
}

/// <summary>
/// Returns all of the items that share the maximum value of a sequence.
/// </summary>
/// <typeparam name="TSource">Type of elements in the sequence.</typeparam>
/// <typeparam name="TKey">Type of keys.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="keySelector">A function to extract a key from an element.</param>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <remarks>
/// <para>
/// This operator is a shortcut for <see cref="DensePartialSortBy{TSource, TKey}(IAsyncEnumerable{TSource}, int,
/// Func{TSource, TKey}, OrderByDirection)"/> with a <c>direction</c> of <see cref="OrderByDirection.Descending"/>
/// and a <c>count</c> of <c>1</c>.
/// </para>
/// <para>
/// This operator uses deferred execution and streams it results.
/// </para>
/// </remarks>
public static IAsyncEnumerable<TSource> MaxItemsBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
return source.DensePartialSortBy(1, keySelector, OrderByDirection.Descending);
}

/// <summary>
/// Returns all of the items that share the maximum value of a sequence.
/// </summary>
/// <typeparam name="TSource">Type of elements in the sequence.</typeparam>
/// <typeparam name="TKey">Type of keys.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="keySelector">A function to extract a key from an element.</param>
/// <param name="comparer">A <see cref="IComparer{T}"/> to compare keys.</param>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <remarks>
/// <para>
/// This operator is a shortcut for <see cref="DensePartialSortBy{TSource, TKey}(IAsyncEnumerable{TSource}, int,
/// Func{TSource, TKey}, IComparer{TKey}?, OrderByDirection)"/> with a <c>direction</c> of <see
/// cref="OrderByDirection.Descending"/> and a <c>count</c> of <c>1</c>.
/// </para>
/// <para>
/// This operator uses deferred execution and streams it results.
/// </para>
/// </remarks>
public static IAsyncEnumerable<TSource> MaxItemsBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer)
{
return source.DensePartialSortBy(1, keySelector, comparer, OrderByDirection.Descending);
}
}
92 changes: 92 additions & 0 deletions Source/SuperLinq.Async/MinItems.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
namespace SuperLinq.Async;

public static partial class AsyncSuperEnumerable
{
/// <summary>
/// Returns all of the items that share the minimum value of a sequence.
/// </summary>
/// <typeparam name="T">Type of elements in the sequence.</typeparam>
/// <param name="source">The source sequence.</param>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <remarks>
/// <para>
/// This operator is a shortcut for <see cref="DensePartialSort{T}(IAsyncEnumerable{T}, int, OrderByDirection)"/> with a
/// <c>direction</c> of <see cref="OrderByDirection.Ascending"/> and a <c>count</c> of <c>1</c>.
/// </para>
/// <para>
/// This operator uses deferred execution and streams it results.
/// </para>
/// </remarks>
public static IAsyncEnumerable<T> MinItems<T>(this IAsyncEnumerable<T> source)
{
return source.DensePartialSort(1, OrderByDirection.Ascending);
}

/// <summary>
/// Returns all of the items that share the minimum value of a sequence.
/// </summary>
/// <typeparam name="T">Type of elements in the sequence.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="comparer">A <see cref="IComparer{T}"/> to compare elements.</param>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <remarks>
/// <para>
/// This operator is a shortcut for <see cref="DensePartialSort{T}(IAsyncEnumerable{T}, int, IComparer{T}?, OrderByDirection)"/> with a
/// <c>count</c> of <c>1</c>.
/// </para>
/// <para>
/// This operator uses deferred execution and streams it results.
/// </para>
/// </remarks>
public static IAsyncEnumerable<T> MinItems<T>(this IAsyncEnumerable<T> source, IComparer<T>? comparer)
{
return source.DensePartialSort(1, comparer, OrderByDirection.Ascending);
}

/// <summary>
/// Returns all of the items that share the minimum value of a sequence.
/// </summary>
/// <typeparam name="TSource">Type of elements in the sequence.</typeparam>
/// <typeparam name="TKey">Type of keys.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="keySelector">A function to extract a key from an element.</param>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <remarks>
/// <para>
/// This operator is a shortcut for <see cref="DensePartialSortBy{TSource, TKey}(IAsyncEnumerable{TSource}, int,
/// Func{TSource, TKey}, OrderByDirection)"/> with a <c>direction</c> of <see cref="OrderByDirection.Ascending"/>
/// and a <c>count</c> of <c>1</c>.
/// </para>
/// <para>
/// This operator uses deferred execution and streams it results.
/// </para>
/// </remarks>
public static IAsyncEnumerable<TSource> MinItemsBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
return source.DensePartialSortBy(1, keySelector, OrderByDirection.Ascending);
}

/// <summary>
/// Returns all of the items that share the minimum value of a sequence.
/// </summary>
/// <typeparam name="TSource">Type of elements in the sequence.</typeparam>
/// <typeparam name="TKey">Type of keys.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="keySelector">A function to extract a key from an element.</param>
/// <param name="comparer">A <see cref="IComparer{T}"/> to compare keys.</param>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <remarks>
/// <para>
/// This operator is a shortcut for <see cref="DensePartialSortBy{TSource, TKey}(IAsyncEnumerable{TSource}, int,
/// Func{TSource, TKey}, IComparer{TKey}?, OrderByDirection)"/> with a <c>direction</c> of <see
/// cref="OrderByDirection.Ascending"/> and a <c>count</c> of <c>1</c>.
/// </para>
/// <para>
/// This operator uses deferred execution and streams it results.
/// </para>
/// </remarks>
public static IAsyncEnumerable<TSource> MinItemsBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer)
{
return source.DensePartialSortBy(1, keySelector, comparer, OrderByDirection.Ascending);
}
}
24 changes: 24 additions & 0 deletions Source/SuperLinq.Async/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,30 @@ select between join techniques of Loop, Hash, and Merge.

This method has 4 overloads.

### MaxItems

Returns all of the elements of the given sequence that share the maximum value.

This method has 2 overloads.

### MaxItemsBy

Returns all of the elements of the given sequence that share the maximum value.

This method has 2 overloads.

### MinItems

Returns all of the elements of the given sequence that share the minimum value.

This method has 2 overloads.

### MinItemsBy

Returns all of the elements of the given sequence that share the minimum value.

This method has 2 overloads.

### OrderBy

Sorts the elements of a sequence in a particular direction (ascending,
Expand Down
92 changes: 92 additions & 0 deletions Source/SuperLinq/MaxItems.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
namespace SuperLinq;

public static partial class SuperEnumerable
{
/// <summary>
/// Returns all of the items that share the maximum value of a sequence.
/// </summary>
/// <typeparam name="T">Type of elements in the sequence.</typeparam>
/// <param name="source">The source sequence.</param>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <remarks>
/// <para>
/// This operator is a shortcut for <see cref="DensePartialSort{T}(IEnumerable{T}, int, OrderByDirection)"/> with a
/// <c>direction</c> of <see cref="OrderByDirection.Descending"/> and a <c>count</c> of <c>1</c>.
/// </para>
/// <para>
/// This operator uses deferred execution and streams it results.
/// </para>
/// </remarks>
public static IEnumerable<T> MaxItems<T>(this IEnumerable<T> source)
{
return source.DensePartialSort(1, OrderByDirection.Descending);
}

/// <summary>
/// Returns all of the items that share the maximum value of a sequence.
/// </summary>
/// <typeparam name="T">Type of elements in the sequence.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="comparer">A <see cref="IComparer{T}"/> to compare elements.</param>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <remarks>
/// <para>
/// This operator is a shortcut for <see cref="DensePartialSort{T}(IEnumerable{T}, int, IComparer{T}?, OrderByDirection)"/> with a
/// <c>count</c> of <c>1</c>.
/// </para>
/// <para>
/// This operator uses deferred execution and streams it results.
/// </para>
/// </remarks>
public static IEnumerable<T> MaxItems<T>(this IEnumerable<T> source, IComparer<T>? comparer)
{
return source.DensePartialSort(1, comparer, OrderByDirection.Descending);
}

/// <summary>
/// Returns all of the items that share the maximum value of a sequence.
/// </summary>
/// <typeparam name="TSource">Type of elements in the sequence.</typeparam>
/// <typeparam name="TKey">Type of keys.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="keySelector">A function to extract a key from an element.</param>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <remarks>
/// <para>
/// This operator is a shortcut for <see cref="DensePartialSortBy{TSource, TKey}(IEnumerable{TSource}, int,
/// Func{TSource, TKey}, OrderByDirection)"/> with a <c>direction</c> of <see cref="OrderByDirection.Descending"/>
/// and a <c>count</c> of <c>1</c>.
/// </para>
/// <para>
/// This operator uses deferred execution and streams it results.
/// </para>
/// </remarks>
public static IEnumerable<TSource> MaxItemsBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
return source.DensePartialSortBy(1, keySelector, OrderByDirection.Descending);
}

/// <summary>
/// Returns all of the items that share the maximum value of a sequence.
/// </summary>
/// <typeparam name="TSource">Type of elements in the sequence.</typeparam>
/// <typeparam name="TKey">Type of keys.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="keySelector">A function to extract a key from an element.</param>
/// <param name="comparer">A <see cref="IComparer{T}"/> to compare keys.</param>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <remarks>
/// <para>
/// This operator is a shortcut for <see cref="DensePartialSortBy{TSource, TKey}(IEnumerable{TSource}, int,
/// Func{TSource, TKey}, IComparer{TKey}?, OrderByDirection)"/> with a <c>direction</c> of <see
/// cref="OrderByDirection.Descending"/> and a <c>count</c> of <c>1</c>.
/// </para>
/// <para>
/// This operator uses deferred execution and streams it results.
/// </para>
/// </remarks>
public static IEnumerable<TSource> MaxItemsBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer)
{
return source.DensePartialSortBy(1, keySelector, comparer, OrderByDirection.Descending);
}
}
Loading

0 comments on commit b8564b5

Please sign in to comment.