Как использовать linq для поиска минимума

У меня есть class A { public float Score; ... } и IEnumerable<A> items и хотелось бы найти A, который имеет минимальный балл.

Использование items.Min(x => x.Score) дает минимальный балл, а не экземпляр с минимальным счетом.

Как я могу получить экземпляр путем повторения только один раз через мои данные?

Изменить. До сих пор существует три основных решения:

  • Написание метода расширения (предлагается Svish). Плюсы: Простая в использовании и оценке Оценка только один раз за элемент. Минусы: требуется метод расширения. (Я выбрал это решение для своего приложения.)

  • Использование агрегата (предложен Даниэлем Реншоу). Плюсы: Использует встроенный метод LINQ. Минусы: Немного запутаны неподготовленному глазу и вызывают оценщика более одного раза.

  • Реализация IComparable (предлагается киберзованием). Плюсы: Можно напрямую использовать Linq.Min. Минусы: Исправлено для одного компаратора - не может свободно выбирать компаратор при выполнении минимального вычисления.

Ответ 1

Посмотрите на метод расширения MinBy в MoreLINQ (созданный Jon Skeet, теперь в основном поддерживаемый Атифом Азизом).

Ответ 2

Использовать агрегирование:

items.Aggregate((c, d) => c.Score < d.Score ? c : d)

Как и предполагалось, точная та же строка с более дружественными именами:

items.Aggregate((minItem, nextItem) => minItem.Score < nextItem.Score ? minItem : nextItem)

Ответ 3

Попробуйте items.OrderBy(s => s.Score).FirstOrDefault();

Ответ 4

Это можно решить с помощью небольшой простой итерации:

float minScore = float.MaxValue;
A minItem = null;

foreach(A item in items)
{
   if(item.Score < minScore)
       minItem = item;
}

return minItem;

Это не хороший запрос LINQ, но он избегает операции сортировки и только выполняет повторный запуск списка в соответствии с требованиями к запросу.

Ответ 5

Быстрый способ, как я вижу, это реализовать IComparable для вашего класса A (если возможно, конечно)

class A : IComparable<A>

Это простая реализация, в которой вы пишете CompareTo(A other), посмотрите IEnumerable (of T).Min на MSDN для справки руководство

Ответ 6

Маленькая складка должна делать:

var minItem = items.Aggregate((acc, c) => acc.Score < c.Score? acc : c);

А... слишком медленно.

Ответ 7

Джейми Пенни получил мой голос. Вы также можете сказать

items.OrderBy(s => s.Score).Take(1);

Что имеет такой же эффект. Используйте Take (5), чтобы взять самые низкие 5 и т.д.