Этот вопрос уже имеет ответ здесь:
У меня есть a class A { public float Score; ... }
и IEnumerable items
и хотел бы найти A
который имеет минимальный счет.
Используя items.Min(x => x.Score)
дает минимальный счет а не экземпляр с минимальным счетом.
Как я могу получить экземпляр путем итерации только однажды через мои данные?
Править: Так долго существует три основных решения:
Запись дополнительного метода (предложенный Svish). Профессионалы: Простой в использовании и оценивает Счет только однажды на объект. Недостатки: Нуждается в дополнительном методе. (Я choosed это решение для моего приложения.)
Используя Агрегат (предложенный Daniel Renshaw). Профессионалы: Использует встроенный метод LINQ. Недостатки: Немного запутываемый к нетренированному глазу и средству анализа вызовов несколько раз.
Реализация IComparable (предложенный киберзетом). Профессионалы: Может использовать Linq. Минута непосредственно. Недостатки: Прикрепленный к одному компаратору - не может свободно выбрать компаратор при выполнении минимального вычисления.
Взгляните на метод расширения MinBy в MoreLINQ (созданный Джоном Скитом, теперь в основном поддерживаемый Атифом Азизом).
Исходный код MinBy (это довольно просто и не зависит от других файлов).
Быстрый способ, как я вижу, это реализация IComparable для вашего класса A (если возможно, конечно)
class A : IComparable<A>
Это простая реализация, в которой вы пишете CompareTo (A other)
посмотрите IEnumerable (of T) .Min в MSDN , чтобы получить справочное руководство
Небольшая складка должна помочь:
var minItem = items.Aggregate((acc, c) => acc.Score < c.Score? acc : c);
Ах ... слишком медленно.
Это можно решить с помощью небольшой простой итерации:
float minScore = float.MaxValue;
A minItem = null;
foreach(A item in items)
{
if(item.Score < minScore)
minItem = item;
}
return minItem;
Это нехороший запрос LINQ, но он избегает операции сортировки и выполняет итерацию списка только один раз в соответствии с требованиями вопроса.
Джейми Пенни получил мой голос. Вы также можете сказать
items.OrderBy(s => s.Score).Take(1);
, что имеет тот же эффект. Используйте Take (5), чтобы взять наименьшие 5 и т. Д.
Использовать агрегирование:
items.Aggregate((c, d) => c.Score < d.Score ? c : d)
Как предлагается, точная та же строка с более понятными именами:
items.Aggregate((minItem, nextItem) => minItem.Score < nextItem.Score ? minItem : nextItem)
Попробуйте items.OrderBy (s => s.Score) .FirstOrDefault ();