MaxBy() is there a way to get multiple max values?

1.2k Views Asked by At

I am trying to get the maximum values out of a list but if there are multiple max values then I want to get all the max values.

For instance I have: Name1, 31 Name2, 35 Name3, 33 Name4, 35

And I want to get: {Name2, 35} AND {Name4, 35}

I tried using MaxBy();

But that only returns the first item(Name2, 35). Any help will be greatly appreciated

struct Amounts
{
    public string Name;
    public int Total;
}

Amount highestAmount = amounts.MaxBy(x => x.Total);

2

There are 2 best solutions below

0
On BEST ANSWER

You can do it by using GroupBy first then using MaxBy on each key. Here is an extension method:

public static IEnumerable<TSource> MaxsBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource,TKey> keySelector)
{
    return source.GroupBy(keySelector).MaxBy(g => g.Key);
}

Here is a working demo:

using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    struct Amounts
    {
        public string Name;
        public int Total;
    }

    public static void Main()
    {
        var amounts = new List<Amounts>
        {
            new Amounts { Name = "Name1", Total = 31 },
            new Amounts { Name = "Name2", Total = 35 },
            new Amounts { Name = "Name3", Total = 32 },
            new Amounts { Name = "Name4", Total = 35 }
        };
        var results = amounts.MaxsBy(x => x.Total);
        Console.WriteLine(string.Join("\n", results.Select(x => x.Name)));
    }
}

public static class Extensions 
{
    public static IEnumerable<TSource> MaxsBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource,TKey> keySelector)
    {
        return source.GroupBy(keySelector).MaxBy(g => g.Key);
    }
}

output

Name2
Name4
1
On

Another method, when you're unable to determine a key for GroupBy (e.g. if your Comparer considers multiple attributes).

    List<T> MultipleMax<T>(IList<T> list, IComparer<T> comparer)
    {
        var max = list.Max(comparer);
        if (max == null)
        {
            return new List<T>();
        }

        return list.Where(t => comparer.Compare(max, t) == 0).ToList();
    }