Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replace WithMin/WithMax methods with MinBy/MaxBy and associated overl…
…oads
- Loading branch information
Showing
6 changed files
with
174 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace Kethane.EnumerableExtensions | ||
{ | ||
public static class MinMaxBy | ||
{ | ||
public static T MinBy<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> selector) | ||
{ | ||
TKey key; | ||
return MinBy(sequence, selector, out key); | ||
} | ||
|
||
public static T MaxBy<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> selector) | ||
{ | ||
TKey key; | ||
return MaxBy(sequence, selector, out key); | ||
} | ||
|
||
public static T MinBy<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> selector, IComparer<TKey> comparer) | ||
{ | ||
TKey key; | ||
return MinBy(sequence, selector, out key, comparer); | ||
} | ||
|
||
public static T MaxBy<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> selector, IComparer<TKey> comparer) | ||
{ | ||
TKey key; | ||
return MaxBy(sequence, selector, out key, comparer); | ||
} | ||
|
||
public static T MinBy<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> selector, out TKey minKey) | ||
{ | ||
return minByImpl(sequence, selector, out minKey, Comparer<TKey>.Default); | ||
} | ||
|
||
public static T MaxBy<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> selector, out TKey maxKey) | ||
{ | ||
return minByImpl(sequence, selector, out maxKey, new ReverseComparer<TKey>(Comparer<TKey>.Default)); | ||
} | ||
|
||
public static T MinBy<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> selector, out TKey minKey, IComparer<TKey> comparer) | ||
{ | ||
if (comparer == null) { throw new ArgumentNullException("comparer"); } | ||
return minByImpl(sequence, selector, out minKey, comparer); | ||
} | ||
|
||
public static T MaxBy<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> selector, out TKey maxKey, IComparer<TKey> comparer) | ||
{ | ||
if (comparer == null) { throw new ArgumentNullException("comparer"); } | ||
return minByImpl(sequence, selector, out maxKey, new ReverseComparer<TKey>(comparer)); | ||
} | ||
|
||
public static T MinByOrDefault<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> selector) | ||
{ | ||
TKey key; | ||
return MinByOrDefault(sequence, selector, out key); | ||
} | ||
|
||
public static T MaxByOrDefault<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> selector) | ||
{ | ||
TKey key; | ||
return MaxByOrDefault(sequence, selector, out key); | ||
} | ||
|
||
public static T MinByOrDefault<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> selector, IComparer<TKey> comparer) | ||
{ | ||
TKey key; | ||
return MinByOrDefault(sequence, selector, out key, comparer); | ||
} | ||
|
||
public static T MaxByOrDefault<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> selector, IComparer<TKey> comparer) | ||
{ | ||
TKey key; | ||
return MaxByOrDefault(sequence, selector, out key, comparer); | ||
} | ||
|
||
public static T MinByOrDefault<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> selector, out TKey minKey) | ||
{ | ||
return minByOrDefaultImpl(sequence, selector, out minKey, Comparer<TKey>.Default); | ||
} | ||
|
||
public static T MaxByOrDefault<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> selector, out TKey maxKey) | ||
{ | ||
return minByOrDefaultImpl(sequence, selector, out maxKey, new ReverseComparer<TKey>(Comparer<TKey>.Default)); | ||
} | ||
|
||
public static T MinByOrDefault<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> selector, out TKey minKey, IComparer<TKey> comparer) | ||
{ | ||
if (comparer == null) { throw new ArgumentNullException("comparer"); } | ||
return minByOrDefaultImpl(sequence, selector, out minKey, comparer); | ||
} | ||
|
||
public static T MaxByOrDefault<T, TKey>(this IEnumerable<T> sequence, Func<T, TKey> selector, out TKey maxKey, IComparer<TKey> comparer) | ||
{ | ||
if (comparer == null) { throw new ArgumentNullException("comparer"); } | ||
return minByOrDefaultImpl(sequence, selector, out maxKey, new ReverseComparer<TKey>(comparer)); | ||
} | ||
|
||
private static T minByImpl<T, TKey>(IEnumerable<T> sequence, Func<T, TKey> selector, out TKey key, IComparer<TKey> comparer) | ||
{ | ||
return minByOrEmpty(sequence, selector, out key, comparer, throwOnEmpty<T>); | ||
} | ||
|
||
private static T minByOrDefaultImpl<T, TKey>(IEnumerable<T> sequence, Func<T, TKey> selector, out TKey key, IComparer<TKey> comparer) | ||
{ | ||
return minByOrEmpty(sequence, selector, out key, comparer, () => default(T)); | ||
} | ||
|
||
private static T throwOnEmpty<T>() | ||
{ | ||
throw new InvalidOperationException("Sequence is empty"); | ||
} | ||
|
||
private static T minByOrEmpty<T, TKey>(IEnumerable<T> sequence, Func<T, TKey> selector, out TKey key, IComparer<TKey> comparer, Func<T> emptyHandler) | ||
{ | ||
if (sequence == null) { throw new ArgumentNullException("sequence"); } | ||
if (selector == null) { throw new ArgumentNullException("selector"); } | ||
|
||
using (var enumerator = sequence.GetEnumerator()) | ||
{ | ||
if (!enumerator.MoveNext()) | ||
{ | ||
T value = emptyHandler(); | ||
key = selector(value); | ||
return value; | ||
} | ||
|
||
T min = enumerator.Current; | ||
TKey minKey = selector(min); | ||
|
||
while (enumerator.MoveNext()) | ||
{ | ||
T current = enumerator.Current; | ||
TKey currentKey = selector(current); | ||
if (comparer.Compare(currentKey, minKey) < 0) | ||
{ | ||
min = current; | ||
minKey = currentKey; | ||
} | ||
} | ||
|
||
key = minKey; | ||
return min; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using System.Collections.Generic; | ||
|
||
namespace Kethane.EnumerableExtensions | ||
{ | ||
internal class ReverseComparer<T> : IComparer<T> | ||
{ | ||
private readonly IComparer<T> comparer; | ||
|
||
public ReverseComparer(IComparer<T> comparer) | ||
{ | ||
this.comparer = comparer; | ||
} | ||
|
||
public int Compare(T x, T y) | ||
{ | ||
int comparison = comparer.Compare(x, y); | ||
if (comparison < 0) { return 1; } | ||
else if (comparison > 0) { return -1; } | ||
else { return 0; } | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters