Skip to content

Instantly share code, notes, and snippets.

@Strilanc
Forked from badmotorfinger/gist:5972009
Last active December 20, 2015 20:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Strilanc/6194382 to your computer and use it in GitHub Desktop.
Save Strilanc/6194382 to your computer and use it in GitHub Desktop.
[Test]
public void TestEmpty()
{
CollectionAssert.AreEqual(
new int[0].MinsBy(i => i),
new int[0]);
}
[Test]
public void TestPreserveOrderAndValue()
{
CollectionAssert.AreEqual(
new int[] {-3,-2,-1,0,1,2,3,4,5,-3}.MinsBy(i => i/2),
new int[] {-3, -2, -3});
}
[Test]
public void TestMinOfDefault()
{
var ints = new[] { 1, 2, 3, 4 };
var result = ints.MinsBy(i => i);
CollectionAssert.AreEqual(new[] { 1 }, result);
}
[Test]
public void TestMinOfDefaultCollection()
{
var ints = new[] { 2, 3, 4, -1, -1 };
var result = ints.MinsBy(i => i);
CollectionAssert.AreEqual(new[] { -1, -1 }, result);
}
/// <summary>
/// Finds an item in the collection with the lowest value. If two or more items have the same value, they are
/// also returned.
/// </summary>
/// <typeparam name="TItem">The source type.</typeparam>
/// <typeparam name="TCompare">The selected value for comparison.</typeparam>
/// <param name="collection">The source collection.</param>
/// <param name="selector">A selector.</param>
/// <returns>A collection of the items with the lowest compared value from the collection.</returns>
public static IReadOnlyList<TItem> MinsBy<TItem, TCompare>(this IEnumerable<TItem> collection, Func<TItem, TCompare> selector)
{
if (collection == null) throw new ArgumentNullException("collection");
if (selector == null) throw new ArgumentNullException("selector");
var minItems = new List<TItem>();
var minImage = default(TCompare);
var comparer = Comparer<TCompare>.Default;
foreach (var item in collection)
{
var image = selector(item);
var compareResult = minItems.Count == 0
? +1
: comparer.Compare(minImage, image);
if (compareResult > 0)
{
minImage = image;
minItems.Clear();
}
if (compareResult >= 0)
{
minItems.Add(item);
}
}
return minItems.AsReadOnly();
}
@badmotorfinger
Copy link

Much better implementation. For backward compatibility I would have used Skip(0) to return the sequence. For. NET 4.5 apps however the IReadOnlyList would be preferable.

@Strilanc
Copy link
Author

Using Skip(0) sounds dangerous... what if Microsoft adds a guard clause that optimizes things by returning the input in that case? Does the documentation/spec guarantee Skip will wrap its input?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment