Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 93 additions & 93 deletions PolyShim/Net60/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,34 @@ internal static class MemberPolyfills_Net60_EnumerableExtensions
{
extension<T>(IEnumerable<T> source)
{
// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.chunk
public IEnumerable<T[]> Chunk(int size)
{
var chunk = new List<T>(size);
foreach (var item in source)
{
chunk.Add(item);
if (chunk.Count == size)
{
yield return chunk.ToArray();
chunk.Clear();
}
}

if (chunk.Count > 0)
yield return chunk.ToArray();
}

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.distinctby#system-linq-enumerable-distinctby-2(system-collections-generic-ienumerable((-0))-system-func((-0-1))-system-collections-generic-iequalitycomparer((-1)))
public IEnumerable<T> DistinctBy<TKey>(
Func<T, TKey> keySelector,
IEqualityComparer<TKey>? comparer
) => source.GroupBy(keySelector, comparer).Select(x => x.First());

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.distinctby#system-linq-enumerable-distinctby-2(system-collections-generic-ienumerable((-0))-system-func((-0-1)))
public IEnumerable<T> DistinctBy<TKey>(Func<T, TKey> keySelector) =>
source.DistinctBy(keySelector, EqualityComparer<TKey>.Default);

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.elementat#system-linq-enumerable-elementat-1(system-collections-generic-ienumerable((-0))-system-index)
public T ElementAt(Index index)
{
Expand Down Expand Up @@ -56,6 +84,26 @@ source as IReadOnlyCollection<T> ??
}
}

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.exceptby#system-linq-enumerable-exceptby-2(system-collections-generic-ienumerable((-0))-system-collections-generic-ienumerable((-1))-system-func((-0-1))-system-collections-generic-iequalitycomparer((-1)))
public IEnumerable<T> ExceptBy<TKey>(
IEnumerable<TKey> other,
Func<T, TKey> keySelector,
IEqualityComparer<TKey>? comparer
)
{
var set = new HashSet<TKey>(other, comparer);

foreach (var item in source)
{
if (!set.Contains(keySelector(item)))
yield return item;
}
}

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.exceptby#system-linq-enumerable-exceptby-2(system-collections-generic-ienumerable((-0))-system-collections-generic-ienumerable((-1))-system-func((-0-1)))
public IEnumerable<T> ExceptBy<TKey>(IEnumerable<TKey> other, Func<T, TKey> keySelector) =>
source.ExceptBy(other, keySelector, EqualityComparer<TKey>.Default);

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.firstordefault#system-linq-enumerable-firstordefault-1(system-collections-generic-ienumerable((-0))-0)
public T FirstOrDefault(T defaultValue)
{
Expand All @@ -77,6 +125,28 @@ public T FirstOrDefault(Func<T, bool> predicate, T defaultValue)
return defaultValue;
}

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.intersectby#system-linq-enumerable-intersectby-2(system-collections-generic-ienumerable((-0))-system-collections-generic-ienumerable((-1))-system-func((-0-1))-system-collections-generic-iequalitycomparer((-1)))
public IEnumerable<T> IntersectBy<TKey>(
IEnumerable<TKey> other,
Func<T, TKey> keySelector,
IEqualityComparer<TKey>? comparer
)
{
var set = new HashSet<TKey>(other, comparer);

foreach (var item in source)
{
if (set.Contains(keySelector(item)))
yield return item;
}
}

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.intersectby#system-linq-enumerable-intersectby-2(system-collections-generic-ienumerable((-0))-system-collections-generic-ienumerable((-1))-system-func((-0-1)))
public IEnumerable<T> IntersectBy<TKey>(
IEnumerable<TKey> other,
Func<T, TKey> keySelector
) => source.IntersectBy(other, keySelector, EqualityComparer<TKey>.Default);

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.lastordefault#system-linq-enumerable-lastordefault-1(system-collections-generic-ienumerable((-0))-0)
public T LastOrDefault(T defaultValue)
{
Expand All @@ -102,6 +172,29 @@ public T LastOrDefault(Func<T, bool> predicate, T defaultValue)
return result;
}

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.max#system-linq-enumerable-max-1(system-collections-generic-ienumerable((-0))-system-collections-generic-icomparer((-0)))
public T? Max(IComparer<T>? comparer) =>
source.OrderByDescending(x => x, comparer).FirstOrDefault();

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.maxby#system-linq-enumerable-maxby-2(system-collections-generic-ienumerable((-0))-system-func((-0-1))-system-collections-generic-icomparer((-1)))
public T? MaxBy<TKey>(Func<T, TKey> keySelector, IComparer<TKey>? comparer) =>
source.OrderByDescending(keySelector, comparer).FirstOrDefault();

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.maxby#system-linq-enumerable-maxby-2(system-collections-generic-ienumerable((-0))-system-func((-0-1)))
public T? MaxBy<TKey>(Func<T, TKey> keySelector) =>
source.MaxBy(keySelector, Comparer<TKey>.Default);

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.min#system-linq-enumerable-min-1(system-collections-generic-ienumerable((-0))-system-collections-generic-icomparer((-0)))
public T? Min(IComparer<T>? comparer) => source.OrderBy(x => x, comparer).FirstOrDefault();

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.minby#system-linq-enumerable-minby-2(system-collections-generic-ienumerable((-0))-system-func((-0-1))-system-collections-generic-icomparer((-1)))
public T? MinBy<TKey>(Func<T, TKey> keySelector, IComparer<TKey>? comparer) =>
source.OrderBy(keySelector, comparer).FirstOrDefault();

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.minby#system-linq-enumerable-minby-2(system-collections-generic-ienumerable((-0))-system-func((-0-1)))
public T? MinBy<TKey>(Func<T, TKey> keySelector) =>
source.MinBy(keySelector, Comparer<TKey>.Default);

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.singleordefault#system-linq-enumerable-singleordefault-1(system-collections-generic-ienumerable((-0))-0)
public T SingleOrDefault(T defaultValue)
{
Expand Down Expand Up @@ -161,81 +254,6 @@ source as IReadOnlyCollection<T> ??
return asCollection.Skip(offset).Take(length);
}

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.min#system-linq-enumerable-min-1(system-collections-generic-ienumerable((-0))-system-collections-generic-icomparer((-0)))
public T? Min(IComparer<T>? comparer) => source.OrderBy(x => x, comparer).FirstOrDefault();

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.minby#system-linq-enumerable-minby-2(system-collections-generic-ienumerable((-0))-system-func((-0-1))-system-collections-generic-icomparer((-1)))
public T? MinBy<TKey>(Func<T, TKey> keySelector, IComparer<TKey>? comparer) =>
source.OrderBy(keySelector, comparer).FirstOrDefault();

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.minby#system-linq-enumerable-minby-2(system-collections-generic-ienumerable((-0))-system-func((-0-1)))
public T? MinBy<TKey>(Func<T, TKey> keySelector) =>
source.MinBy(keySelector, Comparer<TKey>.Default);

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.max#system-linq-enumerable-max-1(system-collections-generic-ienumerable((-0))-system-collections-generic-icomparer((-0)))
public T? Max(IComparer<T>? comparer) =>
source.OrderByDescending(x => x, comparer).FirstOrDefault();

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.maxby#system-linq-enumerable-maxby-2(system-collections-generic-ienumerable((-0))-system-func((-0-1))-system-collections-generic-icomparer((-1)))
public T? MaxBy<TKey>(Func<T, TKey> keySelector, IComparer<TKey>? comparer) =>
source.OrderByDescending(keySelector, comparer).FirstOrDefault();

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.maxby#system-linq-enumerable-maxby-2(system-collections-generic-ienumerable((-0))-system-func((-0-1)))
public T? MaxBy<TKey>(Func<T, TKey> keySelector) =>
source.MaxBy(keySelector, Comparer<TKey>.Default);

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.distinctby#system-linq-enumerable-distinctby-2(system-collections-generic-ienumerable((-0))-system-func((-0-1))-system-collections-generic-iequalitycomparer((-1)))
public IEnumerable<T> DistinctBy<TKey>(
Func<T, TKey> keySelector,
IEqualityComparer<TKey>? comparer
) => source.GroupBy(keySelector, comparer).Select(x => x.First());

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.distinctby#system-linq-enumerable-distinctby-2(system-collections-generic-ienumerable((-0))-system-func((-0-1)))
public IEnumerable<T> DistinctBy<TKey>(Func<T, TKey> keySelector) =>
source.DistinctBy(keySelector, EqualityComparer<TKey>.Default);

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.exceptby#system-linq-enumerable-exceptby-2(system-collections-generic-ienumerable((-0))-system-collections-generic-ienumerable((-1))-system-func((-0-1))-system-collections-generic-iequalitycomparer((-1)))
public IEnumerable<T> ExceptBy<TKey>(
IEnumerable<TKey> other,
Func<T, TKey> keySelector,
IEqualityComparer<TKey>? comparer
)
{
var set = new HashSet<TKey>(other, comparer);

foreach (var item in source)
{
if (!set.Contains(keySelector(item)))
yield return item;
}
}

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.exceptby#system-linq-enumerable-exceptby-2(system-collections-generic-ienumerable((-0))-system-collections-generic-ienumerable((-1))-system-func((-0-1)))
public IEnumerable<T> ExceptBy<TKey>(IEnumerable<TKey> other, Func<T, TKey> keySelector) =>
source.ExceptBy(other, keySelector, EqualityComparer<TKey>.Default);

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.intersectby#system-linq-enumerable-intersectby-2(system-collections-generic-ienumerable((-0))-system-collections-generic-ienumerable((-1))-system-func((-0-1))-system-collections-generic-iequalitycomparer((-1)))
public IEnumerable<T> IntersectBy<TKey>(
IEnumerable<TKey> other,
Func<T, TKey> keySelector,
IEqualityComparer<TKey>? comparer
)
{
var set = new HashSet<TKey>(other, comparer);

foreach (var item in source)
{
if (set.Contains(keySelector(item)))
yield return item;
}
}

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.intersectby#system-linq-enumerable-intersectby-2(system-collections-generic-ienumerable((-0))-system-collections-generic-ienumerable((-1))-system-func((-0-1)))
public IEnumerable<T> IntersectBy<TKey>(
IEnumerable<TKey> other,
Func<T, TKey> keySelector
) => source.IntersectBy(other, keySelector, EqualityComparer<TKey>.Default);

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.unionby#system-linq-enumerable-unionby-2(system-collections-generic-ienumerable((-0))-system-collections-generic-ienumerable((-0))-system-func((-0-1))-system-collections-generic-iequalitycomparer((-1)))
public IEnumerable<T> UnionBy<TKey>(
IEnumerable<T> other,
Expand All @@ -262,24 +280,6 @@ public IEnumerable<T> UnionBy<TKey>(
public IEnumerable<T> UnionBy<TKey>(IEnumerable<T> other, Func<T, TKey> keySelector) =>
source.UnionBy(other, keySelector, EqualityComparer<TKey>.Default);

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.chunk
public IEnumerable<T[]> Chunk(int size)
{
var chunk = new List<T>(size);
foreach (var item in source)
{
chunk.Add(item);
if (chunk.Count == size)
{
yield return chunk.ToArray();
chunk.Clear();
}
}

if (chunk.Count > 0)
yield return chunk.ToArray();
}

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.zip#system-linq-enumerable-zip-3(system-collections-generic-ienumerable((-0))-system-collections-generic-ienumerable((-1))-system-collections-generic-ienumerable((-2)))
public IEnumerable<(T, TSecond, TThird)> Zip<TSecond, TThird>(
IEnumerable<TSecond> second,
Expand Down
8 changes: 4 additions & 4 deletions PolyShim/Net80/CollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ public void AddRange(ReadOnlySpan<T> source)
list.Add(item);
}

// https://learn.microsoft.com/dotnet/api/system.collections.generic.collectionextensions.insertrange
public void InsertRange(int index, ReadOnlySpan<T> source) =>
list.InsertRange(index, source.ToArray());

// https://learn.microsoft.com/dotnet/api/system.collections.generic.collectionextensions.copyto
public void CopyTo(Span<T> destination)
{
Expand All @@ -33,6 +29,10 @@ public void CopyTo(Span<T> destination)
for (var i = 0; i < list.Count; i++)
destination[i] = list[i];
}

// https://learn.microsoft.com/dotnet/api/system.collections.generic.collectionextensions.insertrange
public void InsertRange(int index, ReadOnlySpan<T> source) =>
list.InsertRange(index, source.ToArray());
}
}
#endif
44 changes: 22 additions & 22 deletions PolyShim/Net90/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,6 @@ internal static class MemberPolyfills_Net90_EnumerableExtensions
{
extension<T>(IEnumerable<T> source)
{
// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.index
public IEnumerable<(int index, T value)> Index() =>
source.Select((value, index) => (index, value));

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.countby
public IEnumerable<KeyValuePair<TKey, int>> CountBy<TKey>(
Func<T, TKey> keySelector,
IEqualityComparer<TKey>? comparer = null
)
where TKey : notnull
{
var counts = new Dictionary<TKey, int>(comparer);

foreach (var item in source)
{
var key = keySelector(item);
counts[key] = counts.TryGetValue(key, out var count) ? count + 1 : 1;
}

return counts;
}

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.aggregateby#system-linq-enumerable-aggregateby-3(system-collections-generic-ienumerable((-0))-system-func((-0-1))-system-func((-1-2))-system-func((-2-0-2))-system-collections-generic-iequalitycomparer((-1)))
public IEnumerable<KeyValuePair<TKey, TAccumulate>> AggregateBy<TKey, TAccumulate>(
Func<T, TKey> keySelector,
Expand Down Expand Up @@ -69,6 +47,28 @@ public IEnumerable<KeyValuePair<TKey, TAccumulate>> AggregateBy<TKey, TAccumulat
)
where TKey : notnull =>
source.AggregateBy(keySelector, _ => seed, accumulator, keyComparer);

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.countby
public IEnumerable<KeyValuePair<TKey, int>> CountBy<TKey>(
Func<T, TKey> keySelector,
IEqualityComparer<TKey>? comparer = null
)
where TKey : notnull
{
var counts = new Dictionary<TKey, int>(comparer);

foreach (var item in source)
{
var key = keySelector(item);
counts[key] = counts.TryGetValue(key, out var count) ? count + 1 : 1;
}

return counts;
}

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.index
public IEnumerable<(int index, T value)> Index() =>
source.Select((value, index) => (index, value));
}
}
#endif
16 changes: 8 additions & 8 deletions PolyShim/NetCore10/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,22 @@ internal static class MemberPolyfills_NetCore10_EnumerableExtensions
{
extension<T>(IEnumerable<T> source)
{
// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.prepend
public IEnumerable<T> Prepend(T element)
// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.append
public IEnumerable<T> Append(T element)
{
yield return element;

foreach (var item in source)
yield return item;

yield return element;
}

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.append
public IEnumerable<T> Append(T element)
// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.prepend
public IEnumerable<T> Prepend(T element)
{
yield return element;

foreach (var item in source)
yield return item;

yield return element;
}

#if (NETFRAMEWORK && !NET40_OR_GREATER)
Expand Down
20 changes: 10 additions & 10 deletions PolyShim/NetCore20/CollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,6 @@ IDictionary<TKey, TValue> dictionary
extension<TKey, TValue>(IDictionary<TKey, TValue> dictionary)
where TKey : notnull
{
// https://learn.microsoft.com/dotnet/api/system.collections.generic.collectionextensions.tryadd
public bool TryAdd(TKey key, TValue value)
{
if (dictionary.ContainsKey(key))
return false;

dictionary.Add(key, value);
return true;
}

// https://learn.microsoft.com/dotnet/api/system.collections.generic.collectionextensions.remove
public bool Remove(TKey key, out TValue value)
{
Expand All @@ -51,6 +41,16 @@ public bool Remove(TKey key, out TValue value)
value = default!;
return false;
}

// https://learn.microsoft.com/dotnet/api/system.collections.generic.collectionextensions.tryadd
public bool TryAdd(TKey key, TValue value)
{
if (dictionary.ContainsKey(key))
return false;

dictionary.Add(key, value);
return true;
}
}
}
#endif
6 changes: 3 additions & 3 deletions PolyShim/NetCore20/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ internal static class MemberPolyfills_NetCore20_EnumerableExtensions
{
extension<T>(IEnumerable<T> source)
{
// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.takelast
public IEnumerable<T> TakeLast(int count) => source.Reverse().Take(count).Reverse();

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.skiplast
public IEnumerable<T> SkipLast(int count) => source.Reverse().Skip(count).Reverse();

// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.takelast
public IEnumerable<T> TakeLast(int count) => source.Reverse().Take(count).Reverse();

#if !NET472_OR_GREATER
// https://learn.microsoft.com/dotnet/api/system.linq.enumerable.tohashset#system-linq-enumerable-tohashset-1(system-collections-generic-ienumerable((-0))-system-collections-generic-iequalitycomparer((-0)))
public HashSet<T> ToHashSet(IEqualityComparer<T> comparer) => new(source, comparer);
Expand Down
Loading
Loading