views:

65

answers:

3

I've got a list defined like this...

var sets = new List<HashSet<int>>(numSets);

Why isn't there an overload so I can sort it like this?

sets.Sort(s => s.Count);

I want the largest set first. What's the easiest way to do that?

+4  A: 

Because List<T> class was introduced in .NET 2.0 and the designers of this class decided so. You could use the OrderByDescending extension method:

sets = sets.OrderByDescending(s => s.Count).ToList();
Darin Dimitrov
@Darin Dimitrov: This will sort in ascending order. The OP wants the largest set first. You need `OrderByDescending`.
Ani
@Ani, correct. I've updated my post to reflect this. Thanks for pointing it out.
Darin Dimitrov
Both solutions look good... I'm going to wait to see who gets more votes before I choose :P Thanks! I like how easy this one is to read.
Mark
+4  A: 

Try this:

sets.Sort((setA, setB) => setB.Count.CompareTo(setA.Count));

This uses the Sort(Comparison<T> comparison) overload of List<T>.Sort. The fact that the expression compares B with A rather than A with B is what produces the descending-by-count order that you require.

The reason your code doesn't work is because List<T>.Sort, unlike Enumerable.OrderByDescending, does not have an overload that accepts a Func<TSource, TKey> key-selector.

@Darin Dimitrov's technique of using OrderByDescending is fine too, but note that this will create a sorted list out of place and reassign the reference you have to the original list to the new, sorted one.

Ani
Oh...so there is an anonymous function overload. I saw that `Comparison<>` thing, but I didn't know what it was.
Mark
Reassigning is fine... but which is more efficient? I'd guess this one because it does it in-place. OTH, his reads more like English.
Mark
@Mark: The in-place one *should* be more efficient. Of course, the only way to find out is by measuring. I agree with you on the readability point. To get the best of both solutions, you might want to consider writing an extension method for `List<T>` with a key-selector parameter.
Ani
A: 

Little confused...

var sw = new Stopwatch();

sw.Start();
for (int i = 0; i < 1000; ++i)
    sets.Sort((s1, s2) => s2.Count.CompareTo(s1.Count));
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);

sw.Start();
for (int i = 0; i < 1000; ++i)
    sets = sets.OrderByDescending(s => s.Count).ToList();
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);

Gives me "1499, 2107", but if I switch the order, I get "589, 2023". Why is there such a big difference?

Mark