Helio Ferreira
Helio Ferreira

Reputation: 173

Linq using max to select a single value

How to get the Property ID 3 ? There is a way to cast result to Conta?

List<Conta> contas = new List<Conta>();

contas.Add(new Conta { ID = 1, Saldo = 30 });
contas.Add(new Conta { ID = 2, Saldo = 50 });
contas.Add(new Conta { ID = 3, Saldo = 100 });

var result = contas.Where(c => c.Saldo == contas.Max(l => l.Saldo)) ;

Upvotes: 1

Views: 3192

Answers (4)

Mathew Spearey
Mathew Spearey

Reputation: 51

Instead of using .Where() use Single() / SingleOrDefault() / First() / FirstOrDefault()

Single will throw an exception if there is 0 or more than 1 elements in the result.

SingleOrDefault will throw an exception if there is more than 1 element in the result.

First will throw if there are no results ( list is empty)

FirstOrDefault will throw if the list is null.

Upvotes: 0

Matthew Watson
Matthew Watson

Reputation: 109567

You want a MaxBy() extension method. These are widely available on NuGet.

Once you have that, the solution become simply:

List<Conta> contas = new List<Conta>();

contas.Add(new Conta { ID = 1, Saldo = 30 });
contas.Add(new Conta { ID = 2, Saldo = 50 });
contas.Add(new Conta { ID = 3, Saldo = 100 });

var result = contas.MaxBy(x => x.Saldo);

Console.WriteLine(result.ID);

Here's a sample implementation of MaxBy() (credits to Jon Skeet et al for this):

public static class EnumerableExt
{
    public static TSource MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
    {
        return source.MaxBy(selector, Comparer<TKey>.Default);
    }

    public static TSource MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector, IComparer<TKey> comparer)
    {
        using (IEnumerator<TSource> sourceIterator = source.GetEnumerator())
        {
            if (!sourceIterator.MoveNext())
            {
                throw new InvalidOperationException("Sequence was empty");
            }

            TSource max = sourceIterator.Current;
            TKey maxKey = selector(max);

            while (sourceIterator.MoveNext())
            {
                TSource candidate = sourceIterator.Current;
                TKey candidateProjected = selector(candidate);

                if (comparer.Compare(candidateProjected, maxKey) > 0)
                {
                    max = candidate;
                    maxKey = candidateProjected;
                }
            }

            return max;
        }
    }
}

Upvotes: 1

Souhaieb Besbes
Souhaieb Besbes

Reputation: 1505

var max = Users.OrderByDescending(x => x.Saldo).FirstOrDefault();

Upvotes: 3

Arturo Menchaca
Arturo Menchaca

Reputation: 15982

Use Single() or First() if you only want one result:

var result = contas.FirstOrDefault(c => c.Saldo == contas.Max(l => l.Saldo));

This will returns the Conta object with maximum Saldo.

Upvotes: 1

Related Questions