Skip to content

Commit

Permalink
intersect by key
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasteles committed May 15, 2023
1 parent 29ba443 commit 5a49fce
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 6 deletions.
20 changes: 14 additions & 6 deletions src/EnumerablePlus/LinqEnumerablePlus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> enumerable)
enumerable.Where(e => e is not null).Select(e => e!.Value);

/// <summary>
/// Enumerate the enumerable to a collection of value tuples (int Index, T Value)
/// Enumerate the source to a collection of value tuples (int Index, T Value)
/// </summary>
/// <param name="enumerable"></param>
/// <typeparam name="T"></typeparam>
Expand All @@ -94,11 +94,11 @@ public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> enumerable)


/// <summary>
/// Return value as singleton enumerable
/// Return value as singleton source
/// </summary>
/// <param name="item"></param>
/// <typeparam name="T"></typeparam>
/// <returns>An enumerable of a single item</returns>
/// <returns>An source of a single item</returns>
public static IEnumerable<T> ToSingleton<T>(this T item) =>
Enumerable.Repeat(item, 1);

Expand Down Expand Up @@ -132,12 +132,12 @@ public static void ForEach<T>(this IEnumerable<T> source, Action<T, int> action)
}

/// <summary>
/// Shuffle an enumerable based on a random object
/// Shuffle an source based on a random object
/// </summary>
/// <param name="source">The sequence of elements</param>
/// <param name="random"></param>
/// <typeparam name="T"></typeparam>
/// <returns>Shuffled enumerable</returns>
/// <returns>Shuffled source</returns>
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random? random = null) =>
source.OrderBy(_ => (random ?? Random.Shared).Next());

Expand Down Expand Up @@ -166,7 +166,7 @@ public static void ForEach<T>(this IEnumerable<T> source, Action<T, int> action)
/// <param name="source">The sequence of elements</param>
/// <param name="random"></param>
/// <typeparam name="T"></typeparam>
/// <returns>Shuffled enumerable</returns>
/// <returns>Shuffled source</returns>
public static T PickRandom<T>(this IEnumerable<T> source, Random? random = null)
{
var rnd = random ?? Random.Shared;
Expand Down Expand Up @@ -199,4 +199,12 @@ enumerable switch
/// <returns></returns>
public static IReadOnlyCollection<T> ToReadOnly<T>(this IEnumerable<T> enumerable) =>
enumerable.ToReadOnlyList();

/// <summary>
/// Produces the set intersection of two sequences according to a specified key selector function.
/// </summary>
public static IEnumerable<T> IntersectBy<T, TKey>(this IEnumerable<T> first,
IEnumerable<T> second, Func<T, TKey> keySelector,
IEqualityComparer<TKey>? comparer = null) =>
first.IntersectBy(second.Select(keySelector), keySelector, comparer);
}
26 changes: 26 additions & 0 deletions tests/CSharpPlus.Tests/EnumerablePlus/LinqEnumerablePlusTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,4 +202,30 @@ public void ShouldParseNonIListToReadOnly(NonEmptySet<int> values)
public void ShouldParseNullCollectionToReadOnly() =>
(null as int[])!.ToReadOnly().Should()
.BeEquivalentTo(Array.Empty<int>());

record Foo(int Id, string Name);

[Test]
public void ShouldIntersectBySelector()
{
Foo both1 = new(10, "Ryu");
Foo both2 = new(20, "Ken");

Foo[] first =
{
new(1, "Alex"), both1, both2, new(2, "Luke"),
};

Foo[] second =
{
new(1, "Chun Li"), both1, both2, new(2, "Blanka"),
};

var result = first.IntersectBy(second, x => x.Name).ToArray();

result.Should().BeEquivalentTo(new[]
{
both1, both2,
});
}
}

0 comments on commit 5a49fce

Please sign in to comment.