mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-22 23:58:48 +00:00
style/perf: reduce complexity of MinMax and MinMaxBy
This commit is contained in:
parent
121c3a388a
commit
e0bdaaddce
@ -1,4 +1,6 @@
|
|||||||
using System.Runtime.InteropServices;
|
#if NET5_0_OR_GREATER
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace X10D.Linq;
|
namespace X10D.Linq;
|
||||||
|
|
||||||
@ -50,38 +52,16 @@ public static class EnumerableExtensions
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
comparer ??= Comparer<T>.Default;
|
comparer ??= Comparer<T>.Default;
|
||||||
T? minValue;
|
|
||||||
T? maxValue;
|
|
||||||
|
|
||||||
// ReSharper disable once PossibleMultipleEnumeration
|
// ReSharper disable once PossibleMultipleEnumeration
|
||||||
if (source.TryGetSpan(out ReadOnlySpan<T> span))
|
if (source.TryGetSpan(out ReadOnlySpan<T> span))
|
||||||
{
|
{
|
||||||
if (span.IsEmpty)
|
return MinMaxSpan(comparer, span);
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Source contains no elements");
|
|
||||||
}
|
|
||||||
|
|
||||||
minValue = span[0];
|
|
||||||
maxValue = minValue;
|
|
||||||
|
|
||||||
for (var index = 1; (uint)index < (uint)span.Length; index++)
|
|
||||||
{
|
|
||||||
T current = span[index];
|
|
||||||
|
|
||||||
if (comparer.Compare(current, minValue) < 0)
|
|
||||||
{
|
|
||||||
minValue = current;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (comparer.Compare(current, maxValue) > 0)
|
|
||||||
{
|
|
||||||
maxValue = current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (minValue, maxValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T? minValue;
|
||||||
|
T? maxValue;
|
||||||
|
|
||||||
// ReSharper disable once PossibleMultipleEnumeration
|
// ReSharper disable once PossibleMultipleEnumeration
|
||||||
using (IEnumerator<T> enumerator = source.GetEnumerator())
|
using (IEnumerator<T> enumerator = source.GetEnumerator())
|
||||||
{
|
{
|
||||||
@ -175,38 +155,16 @@ public static class EnumerableExtensions
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
comparer ??= Comparer<TResult>.Default;
|
comparer ??= Comparer<TResult>.Default;
|
||||||
TResult? minValue;
|
|
||||||
TResult? maxValue;
|
|
||||||
|
|
||||||
// ReSharper disable once PossibleMultipleEnumeration
|
// ReSharper disable once PossibleMultipleEnumeration
|
||||||
if (source.TryGetSpan(out ReadOnlySpan<TSource> span))
|
if (source.TryGetSpan(out ReadOnlySpan<TSource> span))
|
||||||
{
|
{
|
||||||
if (span.IsEmpty)
|
return MinMaxSpan(selector, comparer, span);
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Source contains no elements");
|
|
||||||
}
|
|
||||||
|
|
||||||
minValue = selector(span[0]);
|
|
||||||
maxValue = minValue;
|
|
||||||
|
|
||||||
for (var index = 1; (uint)index < (uint)span.Length; index++)
|
|
||||||
{
|
|
||||||
TResult current = selector(span[index]);
|
|
||||||
|
|
||||||
if (minValue is null || comparer.Compare(current, minValue) < 0)
|
|
||||||
{
|
|
||||||
minValue = current;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxValue is null || comparer.Compare(current, maxValue) > 0)
|
|
||||||
{
|
|
||||||
maxValue = current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (minValue, maxValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TResult? minValue;
|
||||||
|
TResult? maxValue;
|
||||||
|
|
||||||
// ReSharper disable once PossibleMultipleEnumeration
|
// ReSharper disable once PossibleMultipleEnumeration
|
||||||
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
|
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
|
||||||
{
|
{
|
||||||
@ -305,31 +263,7 @@ public static class EnumerableExtensions
|
|||||||
// ReSharper disable once PossibleMultipleEnumeration
|
// ReSharper disable once PossibleMultipleEnumeration
|
||||||
if (source.TryGetSpan(out ReadOnlySpan<TSource> span))
|
if (source.TryGetSpan(out ReadOnlySpan<TSource> span))
|
||||||
{
|
{
|
||||||
if (span.IsEmpty)
|
return MinMaxSelectedSpan(keySelector, comparer, span);
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Source contains no elements");
|
|
||||||
}
|
|
||||||
|
|
||||||
minValue = span[0];
|
|
||||||
maxValue = minValue;
|
|
||||||
|
|
||||||
for (var index = 1; (uint)index < (uint)span.Length; index++)
|
|
||||||
{
|
|
||||||
TSource current = span[index];
|
|
||||||
TResult transformedCurrent = keySelector(current);
|
|
||||||
|
|
||||||
if (minValue is null || comparer.Compare(transformedCurrent, keySelector(minValue)) < 0)
|
|
||||||
{
|
|
||||||
minValue = current;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxValue is null || comparer.Compare(transformedCurrent, keySelector(maxValue)) > 0)
|
|
||||||
{
|
|
||||||
maxValue = current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (minValue, maxValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReSharper disable once PossibleMultipleEnumeration
|
// ReSharper disable once PossibleMultipleEnumeration
|
||||||
@ -363,6 +297,95 @@ public static class EnumerableExtensions
|
|||||||
return (minValue, maxValue);
|
return (minValue, maxValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static (T? Minimum, T? Maximum) MinMaxSpan<T>(IComparer<T> comparer, ReadOnlySpan<T> span)
|
||||||
|
{
|
||||||
|
if (span.IsEmpty)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Source contains no elements");
|
||||||
|
}
|
||||||
|
|
||||||
|
T minValue = span[0];
|
||||||
|
T maxValue = minValue;
|
||||||
|
|
||||||
|
for (var index = 1; (uint)index < (uint)span.Length; index++)
|
||||||
|
{
|
||||||
|
T current = span[index];
|
||||||
|
|
||||||
|
if (comparer.Compare(current, minValue) < 0)
|
||||||
|
{
|
||||||
|
minValue = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comparer.Compare(current, maxValue) > 0)
|
||||||
|
{
|
||||||
|
maxValue = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (minValue, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (TSource? Minimum, TSource? Maximum) MinMaxSelectedSpan<TSource, TResult>(Func<TSource, TResult> keySelector,
|
||||||
|
IComparer<TResult> comparer,
|
||||||
|
ReadOnlySpan<TSource> span)
|
||||||
|
{
|
||||||
|
if (span.IsEmpty)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Source contains no elements");
|
||||||
|
}
|
||||||
|
|
||||||
|
TSource minValue = span[0];
|
||||||
|
TSource maxValue = minValue;
|
||||||
|
|
||||||
|
for (var index = 1; (uint)index < (uint)span.Length; index++)
|
||||||
|
{
|
||||||
|
TSource current = span[index];
|
||||||
|
TResult transformedCurrent = keySelector(current);
|
||||||
|
|
||||||
|
if (minValue is null || comparer.Compare(transformedCurrent, keySelector(minValue)) < 0)
|
||||||
|
{
|
||||||
|
minValue = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxValue is null || comparer.Compare(transformedCurrent, keySelector(maxValue)) > 0)
|
||||||
|
{
|
||||||
|
maxValue = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (minValue, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (TResult?, TResult?) MinMaxSpan<TSource, TResult>(Func<TSource, TResult> selector,
|
||||||
|
IComparer<TResult> comparer,
|
||||||
|
ReadOnlySpan<TSource> span)
|
||||||
|
{
|
||||||
|
if (span.IsEmpty)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Source contains no elements");
|
||||||
|
}
|
||||||
|
|
||||||
|
TResult minValue = selector(span[0]);
|
||||||
|
TResult maxValue = minValue;
|
||||||
|
|
||||||
|
for (var index = 1; (uint)index < (uint)span.Length; index++)
|
||||||
|
{
|
||||||
|
TResult current = selector(span[index]);
|
||||||
|
|
||||||
|
if (minValue is null || comparer.Compare(current, minValue) < 0)
|
||||||
|
{
|
||||||
|
minValue = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxValue is null || comparer.Compare(current, maxValue) > 0)
|
||||||
|
{
|
||||||
|
maxValue = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (minValue, maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
private static bool TryGetSpan<TSource>(this IEnumerable<TSource> source, out ReadOnlySpan<TSource> span)
|
private static bool TryGetSpan<TSource>(this IEnumerable<TSource> source, out ReadOnlySpan<TSource> span)
|
||||||
{
|
{
|
||||||
#if NET6_0_OR_GREATER
|
#if NET6_0_OR_GREATER
|
||||||
|
Loading…
Reference in New Issue
Block a user