Ответ 1
Посмотрите на метод расширения MinBy в MoreLINQ (созданный Jon Skeet, теперь в основном поддерживаемый Атифом Азизом).
-
Исходный код MinBy (он довольно прост и не имеет зависимости от других файлов).
У меня есть class A { public float Score; ... }
и IEnumerable<A> items
и хотелось бы найти A
, который имеет минимальный балл.
Использование items.Min(x => x.Score)
дает минимальный балл, а не экземпляр с минимальным счетом.
Как я могу получить экземпляр путем повторения только один раз через мои данные?
Изменить. До сих пор существует три основных решения:
Написание метода расширения (предлагается Svish). Плюсы: Простая в использовании и оценке Оценка только один раз за элемент. Минусы: требуется метод расширения. (Я выбрал это решение для своего приложения.)
Использование агрегата (предложен Даниэлем Реншоу). Плюсы: Использует встроенный метод LINQ. Минусы: Немного запутаны неподготовленному глазу и вызывают оценщика более одного раза.
Реализация IComparable (предлагается киберзованием). Плюсы: Можно напрямую использовать Linq.Min. Минусы: Исправлено для одного компаратора - не может свободно выбирать компаратор при выполнении минимального вычисления.
Посмотрите на метод расширения MinBy в MoreLINQ (созданный Jon Skeet, теперь в основном поддерживаемый Атифом Азизом).
Исходный код MinBy (он довольно прост и не имеет зависимости от других файлов).
Использовать агрегирование:
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();
Это можно решить с помощью небольшой простой итерации:
float minScore = float.MaxValue;
A minItem = null;
foreach(A item in items)
{
if(item.Score < minScore)
minItem = item;
}
return minItem;
Это не хороший запрос LINQ, но он избегает операции сортировки и только выполняет повторный запуск списка в соответствии с требованиями к запросу.
Быстрый способ, как я вижу, это реализовать 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);
А... слишком медленно.
Джейми Пенни получил мой голос. Вы также можете сказать
items.OrderBy(s => s.Score).Take(1);
Что имеет такой же эффект. Используйте Take (5), чтобы взять самые низкие 5 и т.д.