Getting the MoreLinq MaxBy function to return more

2019-09-16 09:58发布

I have a situation in which I have a list of objects with an int property and I need to retrieve the 3 objects with the highest value for that property. The MoreLinq MaxBy function is very convenient to find the single highest, but is there a way I can use that to find the 3 highest? (Not necessarily of the same value). The implementation I'm currently using is to find the single highest with MaxBy, remove that object from the list and call MaxBy again, etc. and then add the objects back into the list once I've found the 3 highest. Just thinking about this implementation makes me cringe and I'd really like to find a better way.

2条回答
虎瘦雄心在
2楼-- · 2019-09-16 10:43

in this case, you could simply do

yourResult.OrderByDescending(m => m.YourIntProperty)
.Take(3);

Now, this will retrieve you 3 objects.

So if you've got 4 objects sharing the same value (which is the max), 1 will be skipped. Not sure if that's what you want, or if it's not a problem...

But MaxBy will also retrieve only one element if you have many elements with the same "max value".

查看更多
Root(大扎)
3楼-- · 2019-09-16 10:50

Update: In version 3, MaxBy (including MinBy) of MoreLINQ was changed to return a sequence as opposed to a single item.

Use MoreLINQ's PartialSort or PartialSortBy. The example below uses PartialSortBy to find and print the longest 5 words in a given text:

var text = @"
    Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    Etiam gravida nec mauris vitae sollicitudin. Suspendisse
    malesuada urna eu mi suscipit fringilla. Donec ut ipsum
    aliquet, tincidunt mi sed, efficitur magna. Nulla sit
    amet congue diam, at posuere lectus. Praesent sit amet
    libero vehicula dui commodo gravida eget a nisi. Sed
    imperdiet arcu eget erat feugiat gravida id non est.
    Nam malesuada nibh sit amet nisl sollicitudin vestibulum.";

var words = Regex.Matches(text, @"\w+");

var top =
    from g in words.Cast<Match>()
                   .Select(m => m.Value)
                   .GroupBy(s => s.Length)
                   .PartialSortBy(5, m => m.Key, OrderByDirection.Descending)
    select g.Key + ": " + g.Distinct().ToDelimitedString(", ");

foreach (var e in top)
    Console.WriteLine(e);

It will print:

14: malesuadafsfjs
12: sollicitudin
11: consectetur, Suspendisse
10: adipiscing, vestibulum
9: malesuada, fringilla, tincidunt, efficitur, imperdiet
查看更多
登录 后发表回答