Запрос Linq для получения отдельного объекта на основе даты и приоритета

#c# #linq #c#-8.0

Вопрос:

У меня есть список объектов со свойствами даты, времени и приоритета.

 public class DayResponse
{
    public DateTime Date { get; set; }
    public int Priority { get; set; }
    ...
}
 

Могут быть объекты с одинаковой датой, но с разным приоритетом (1 — наивысший приоритет, 6 — самый низкий), а затем я хочу получить объект с наивысшим (наименьшим значением int) приоритетом. Таким образом, результатом должен быть список с объектами со всеми уникальными датами, а там, где были «конфликты», тот, у которого наивысший приоритет, является тем, который в результате. Есть ли linqquery для выполнения этого? Я знаю, что могу получить разные даты, а затем перебирать их, и если на одну и ту же дату приходится более одной, получите наивысший приоритет, но с linq всегда хорошо 🙂 У меня есть пакет MoreLINQ, так что DistinctBy существует.

Ответ №1:

Вы можете сгруппировать записи по их Date признаку , а затем выбрать ту , которая используется с наименьшим Priority использованием MinBy .

 sequence.GroupBy(d => d.Date).Select(g => g.MinBy(d => d.Priority));
 

MinBy доступен из коробки с System.Linq тех пор .NET 6 . Он также может быть взят из MoreLinq , но обратите внимание, что в MoreLinq возвращаемом типе есть перечисляемый, содержащий все значения, которые имеют одинаковый минимальный приоритет, поэтому вам нужно использовать SelectMany :

 sequence.GroupBy(d => d.Date).SelectMany(g => g.MinBy(d => d.Priority));
 

Демо-версия для .NET 6:

 using System;
using System.Linq;

var sequence = new DayResponse[] {
    new() { Date = new DateTime(2000, 01, 01), Priority = 1},
    new() { Date = new DateTime(2001, 01, 01), Priority = 2},
    new() { Date = new DateTime(2001, 01, 01), Priority = 5},
};

var distinct = sequence.GroupBy(d => d.Date).Select(g => g.MinBy(d => d.Priority));

foreach (var x in distinct)
{
    Console.WriteLine($"DayResponse: Date = {x.Date}, Priority = {x.Priority}");
}

public class DayResponse
{
    public DateTime Date { get; set; }
    public int Priority { get; set; }
}
 

Доступно здесь: https://dotnetfiddle.net/SLnkSr

Комментарии:

1. Я не хочу указывать версию c #, поэтому некоторые части предоставленного кода мне приходится переписывать, но поскольку я запускаю это в Core 3.1 c # 8, я не знаю, есть ли какие-то языковые возможности, которые мне не хватает, но для меня distinct — это IEnumerable<IExtremaEnumerable<DayResponse>> и xне удается разрешить дату или приоритет

2. @Hyzac Мой плохой, я забыл, что MoreLINQ имеет другую подпись MinBy и возвращает все элементы, которые имеют одинаковое значение, на которое вы хотите минимизировать. Обновил ответ, чтобы отразить это.