Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HasDuplicates operator #430

Merged
72 changes: 72 additions & 0 deletions Source/SuperLinq.Async/HasDuplicates.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
namespace SuperLinq.Async;

public static partial class AsyncSuperEnumerable
{
/// <summary>
/// Checks if sequence contains duplicates
/// </summary>
/// <param name="source">The sequence to check.</param>
/// <typeparam name="T">The type of the elements in the source sequence</typeparam>
/// <returns>
/// <see langword="true"/> if any element of the sequence <paramref name="source" /> is duplicated, <see langword="false"/> otherwise
/// </returns>
public static ValueTask<bool> HasDuplicates<T>(this IAsyncEnumerable<T> source)
=> source?.HasDuplicates(EqualityComparer<T>.Default) ?? throw new ArgumentNullException(nameof(source));
julienasp marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Checks if sequence contains duplicates, using the specified element equality comparer
/// </summary>
/// <param name="source">The sequence to check.</param>
/// <param name="comparer">The equality comparer to use to determine whether or not keys are equal.
/// If null, the default equality comparer for <c>TSource</c> is used.</param>
/// <typeparam name="T">The type of the elements in the source sequence</typeparam>
/// <returns>
/// <see langword="true"/> if any element of the sequence <paramref name="source" /> is duplicated, <see langword="false"/> otherwise
/// </returns>
public static ValueTask<bool> HasDuplicates<T>(this IAsyncEnumerable<T> source, IEqualityComparer<T>? comparer)
=> source?.HasDuplicates(Identity, comparer) ?? throw new ArgumentNullException(nameof(source));

/// <summary>
/// Checks if sequence contains duplicates, using the specified element equality comparer
/// </summary>
/// <param name="source">The sequence to check.</param>
/// <param name="keySelector">Projection for determining "distinctness"</param>
/// <typeparam name="TSource">Type of the source sequence</typeparam>
/// <typeparam name="TKey">Type of the projected element</typeparam>
/// <returns>
/// <see langword="true"/> if any element of the sequence <paramref name="source" /> is duplicated, <see langword="false"/> otherwise
/// </returns>
public static ValueTask<bool> HasDuplicates<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
=> source?.HasDuplicates(keySelector, EqualityComparer<TKey>.Default) ?? throw new ArgumentNullException(nameof(source));

/// <summary>
/// Checks if sequence contains duplicates, using the specified element equality comparer
/// </summary>
/// <param name="source">The sequence to check.</param>
/// <param name="keySelector">Projection for determining "distinctness"</param>
/// <param name="comparer">The equality comparer to use to determine whether or not keys are equal.
/// If null, the default equality comparer for <c>TSource</c> is used.</param>
/// <typeparam name="TSource">Type of the source sequence</typeparam>
/// <typeparam name="TKey">Type of the projected element</typeparam>
/// <returns>
/// <see langword="true"/> if any element of the sequence <paramref name="source" /> is duplicated, <see langword="false"/> otherwise
/// </returns>
public static async ValueTask<bool> HasDuplicates<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer)
{
Guard.IsNotNull(source);
Guard.IsNotNull(keySelector);

var enumeratedElements = new HashSet<TKey>(comparer);

await foreach (var element in source.ConfigureAwait(false))
{
if (enumeratedElements.Add(keySelector(element)) is false)
julienasp marked this conversation as resolved.
Show resolved Hide resolved
{
return true;
}
}

return false;
}
}

Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
#nullable enable
static SuperLinq.Async.AsyncSuperEnumerable.HasDuplicates<T>(this System.Collections.Generic.IAsyncEnumerable<T>! source) -> System.Threading.Tasks.ValueTask<bool>
static SuperLinq.Async.AsyncSuperEnumerable.HasDuplicates<T>(this System.Collections.Generic.IAsyncEnumerable<T>! source, System.Collections.Generic.IEqualityComparer<T>? comparer) -> System.Threading.Tasks.ValueTask<bool>
static SuperLinq.Async.AsyncSuperEnumerable.HasDuplicates<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector) -> System.Threading.Tasks.ValueTask<bool>
static SuperLinq.Async.AsyncSuperEnumerable.HasDuplicates<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) -> System.Threading.Tasks.ValueTask<bool>
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
#nullable enable
static SuperLinq.Async.AsyncSuperEnumerable.HasDuplicates<T>(this System.Collections.Generic.IAsyncEnumerable<T>! source) -> System.Threading.Tasks.ValueTask<bool>
static SuperLinq.Async.AsyncSuperEnumerable.HasDuplicates<T>(this System.Collections.Generic.IAsyncEnumerable<T>! source, System.Collections.Generic.IEqualityComparer<T>? comparer) -> System.Threading.Tasks.ValueTask<bool>
static SuperLinq.Async.AsyncSuperEnumerable.HasDuplicates<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector) -> System.Threading.Tasks.ValueTask<bool>
static SuperLinq.Async.AsyncSuperEnumerable.HasDuplicates<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) -> System.Threading.Tasks.ValueTask<bool>
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
#nullable enable
static SuperLinq.Async.AsyncSuperEnumerable.HasDuplicates<T>(this System.Collections.Generic.IAsyncEnumerable<T>! source) -> System.Threading.Tasks.ValueTask<bool>
static SuperLinq.Async.AsyncSuperEnumerable.HasDuplicates<T>(this System.Collections.Generic.IAsyncEnumerable<T>! source, System.Collections.Generic.IEqualityComparer<T>? comparer) -> System.Threading.Tasks.ValueTask<bool>
static SuperLinq.Async.AsyncSuperEnumerable.HasDuplicates<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector) -> System.Threading.Tasks.ValueTask<bool>
static SuperLinq.Async.AsyncSuperEnumerable.HasDuplicates<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) -> System.Threading.Tasks.ValueTask<bool>
62 changes: 62 additions & 0 deletions Source/SuperLinq/HasDuplicates.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
namespace SuperLinq;

public static partial class SuperEnumerable
{
/// <summary>
/// Checks if sequence contains duplicates
/// </summary>
/// <param name="source">The sequence to check.</param>
/// <typeparam name="T">The type of the elements in the source sequence</typeparam>
/// <returns>
/// <see langword="true"/> if any element of the sequence <paramref name="source" /> is duplicated, <see langword="false"/> otherwise
/// </returns>
public static bool HasDuplicates<T>(this IEnumerable<T> source)
=> source?.HasDuplicates(EqualityComparer<T>.Default) ?? throw new ArgumentNullException(nameof(source));

/// <summary>
/// Checks if sequence contains duplicates, using the specified element equality comparer
/// </summary>
/// <param name="source">The sequence to check.</param>
/// <param name="comparer">The equality comparer to use to determine whether or not keys are equal.
/// If null, the default equality comparer for <c>TSource</c> is used.</param>
/// <typeparam name="T">The type of the elements in the source sequence</typeparam>
/// <returns>
/// <see langword="true"/> if any element of the sequence <paramref name="source" /> is duplicated, <see langword="false"/> otherwise
/// </returns>
public static bool HasDuplicates<T>(this IEnumerable<T> source, IEqualityComparer<T>? comparer)
=> source?.HasDuplicates(Identity, comparer) ?? throw new ArgumentNullException(nameof(source));

/// <summary>
/// Checks if sequence contains duplicates, using the specified element equality comparer
/// </summary>
/// <param name="source">The sequence to check.</param>
/// <param name="keySelector">Projection for determining "distinctness"</param>
/// <typeparam name="TSource">Type of the source sequence</typeparam>
/// <typeparam name="TKey">Type of the projected element</typeparam>
/// <returns>
/// <see langword="true"/> if any element of the sequence <paramref name="source" /> is duplicated, <see langword="false"/> otherwise
/// </returns>
public static bool HasDuplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
=> source?.HasDuplicates(keySelector, EqualityComparer<TKey>.Default) ?? throw new ArgumentNullException(nameof(source));

/// <summary>
/// Checks if sequence contains duplicates, using the specified element equality comparer
/// </summary>
/// <param name="source">The sequence to check.</param>
/// <param name="keySelector">Projection for determining "distinctness"</param>
/// <param name="comparer">The equality comparer to use to determine whether or not keys are equal.
/// If null, the default equality comparer for <c>TSource</c> is used.</param>
/// <typeparam name="TSource">Type of the source sequence</typeparam>
/// <typeparam name="TKey">Type of the projected element</typeparam>
/// <returns>
/// <see langword="true"/> if any element of the sequence <paramref name="source" /> is duplicated, <see langword="false"/> otherwise
/// </returns>
public static bool HasDuplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer)
{
Guard.IsNotNull(source);
Guard.IsNotNull(keySelector);

var enumeratedElements = new HashSet<TKey>(comparer);
julienasp marked this conversation as resolved.
Show resolved Hide resolved
return source.Any(element => !enumeratedElements.Add(keySelector(element)));
julienasp marked this conversation as resolved.
Show resolved Hide resolved
}
}
4 changes: 4 additions & 0 deletions Source/SuperLinq/PublicAPI/net6.0/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
#nullable enable
static SuperLinq.SuperEnumerable.HasDuplicates<T>(this System.Collections.Generic.IEnumerable<T>! source) -> bool
static SuperLinq.SuperEnumerable.HasDuplicates<T>(this System.Collections.Generic.IEnumerable<T>! source, System.Collections.Generic.IEqualityComparer<T>? comparer) -> bool
static SuperLinq.SuperEnumerable.HasDuplicates<TSource, TKey>(this System.Collections.Generic.IEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector) -> bool
static SuperLinq.SuperEnumerable.HasDuplicates<TSource, TKey>(this System.Collections.Generic.IEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) -> bool
4 changes: 4 additions & 0 deletions Source/SuperLinq/PublicAPI/net7.0/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
#nullable enable
static SuperLinq.SuperEnumerable.HasDuplicates<T>(this System.Collections.Generic.IEnumerable<T>! source) -> bool
static SuperLinq.SuperEnumerable.HasDuplicates<T>(this System.Collections.Generic.IEnumerable<T>! source, System.Collections.Generic.IEqualityComparer<T>? comparer) -> bool
static SuperLinq.SuperEnumerable.HasDuplicates<TSource, TKey>(this System.Collections.Generic.IEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector) -> bool
static SuperLinq.SuperEnumerable.HasDuplicates<TSource, TKey>(this System.Collections.Generic.IEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) -> bool
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
#nullable enable
static SuperLinq.SuperEnumerable.HasDuplicates<T>(this System.Collections.Generic.IEnumerable<T>! source) -> bool
static SuperLinq.SuperEnumerable.HasDuplicates<T>(this System.Collections.Generic.IEnumerable<T>! source, System.Collections.Generic.IEqualityComparer<T>? comparer) -> bool
static SuperLinq.SuperEnumerable.HasDuplicates<TSource, TKey>(this System.Collections.Generic.IEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector) -> bool
static SuperLinq.SuperEnumerable.HasDuplicates<TSource, TKey>(this System.Collections.Generic.IEnumerable<TSource>! source, System.Func<TSource, TKey>! keySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) -> bool
Loading