Does C# have a std::nth_element equivalent?
Asked Answered
M

3

17

I'm porting some C++ code to C#.

Does C# have an equivalent to std::nth_element() or do I need to roll my own?

Mountie answered 29/3, 2010 at 19:15 Comment(0)
N
10

I presume you are looking for an accessor that returns the Nth element of an unordered collection by performing a partial-sort on the collection. This tends to be useful when you have a very large collection and are interested in one of the first elements based on some ordering predicate.

To my knowledge, neither the .NET BCL or LINQ extensions offer an equivalent. All of the sorting methods (including Enumerable.OrderBy) perform a complete ordering of the collection.

If you need an efficient version of Nth, you will need to roll your own extension method on IEnumerable to do so. If you are going to roll you own you may want to look into the Quick Select algorithm, which has O(n) performance.

If the brute-force version is sufficient, you could use LINQ:

var someCollection = new []{ 5, 2, 8, 9, 0, 1, 3, 12, 4 };

var fifthItem = someCollection.NthItem(5);

public static class NthExtensions 
{
    public static T NthItem(this IEnumerable<T> coll, int n) 
    {
        return coll.OrderBy(x => x).Skip(n - 1).First();
    }
}
Nostomania answered 29/3, 2010 at 19:19 Comment(0)
M
3

No, it doesn't. You'll have to write the selection algorithm (preferrably quick select) by hand.

Matrimony answered 29/3, 2010 at 19:18 Comment(0)
T
1

There isn't a direct equivalent. You could, potentially, use LINQ's OrderBy and Take/Skip to acheive the same goals on any IEnumerable, but the entire collection will get sorted in this process.

Teets answered 29/3, 2010 at 19:21 Comment(3)
I'm wondering whether, in case OrderBy is implemented functionally (e.g. by merge sort), the combination of take/skip plus lazy evaluation won't actually just perform a partial sort as requested. head (sort list)) in Haskell - for example - is a valid O(n) approach for finding a list's minimum. Any hints?Matrimony
@Dario: Theoretically, it ~could~, but the current implementation does not.Teets
Would have been funny though :)Matrimony

© 2022 - 2024 — McMap. All rights reserved.