C # поиск списка с помощью группового и где - PullRequest
0 голосов
/ 25 мая 2018

Я пытаюсь найти пустой временной интервал при поиске нескольких клиентов по номеру слота.Если время доступно для этого клиента, оно должно вернуть первого найденного клиента.

Пример данных (У каждого клиента есть уникальный номер слота)

customer 1: slotnumber 0, time 0
customer 1: slotnumber 0, time 1
customer 1: slotnumber 0, time 2
customer 1: slotnumber 0, time 4

customer 2: slotnumber 1, time 0
customer 2: slotnumber 1, time 1

У меня есть следующий класс:

public class CustomerSlot
{
    public int customerid { get; set; }  
    public int slotnumber { get; set; }  
    public int time { get; set; }
}

Затем у меня есть список слотов клиентов:

List<CustomerSlot> lstCustomerSlots = new List<CustomerSlot>();

Теперь предположим, что я хочу найти первый слот со временем 3, используя вышеуказанные данные.

Здесь мне нужна помощь.У меня не совсем правильный синтаксис для группировки по клиенту и возвращения клиента, у которого есть этот доступный интервал времени:

CustomerSlot timeSpaceFound = lstCustomerSlots
                                  .Where(t => t.time != 3)   // Search for time 3
                                  .GroupBy(c => c.customerid) // Search an entire customer
                                  .OrderBy(c => c.customerid) // Start searching by the order of first customerid
                                  .FirstOrDefault();

Любая помощь в настройке лямбда выше будет принята.Не нашли ни одного примера поиска решения онлайн.Спасибо.

Ответы [ 2 ]

0 голосов
/ 25 мая 2018

Если я правильно понимаю, вы хотите выбрать из своего списка первого клиента, у которого уже нет записи временного интервала для 3.

CustomerSlot timeSpaceFound = lstCustomerSlots
                                  .GroupBy(c => c.customerid) // Group entries by customer
                                  .Where(g => g.All(c => c.time != 3)) // Remove all groups that have a time entry of 3
                                  .OrderBy(g => g.Key) // Start searching by the order of first customerid
                                  .FirstOrDefault() // Select the first group
                                  ?.FirstOrDefault(); // Select the first CustomerSlot entry in the group.
0 голосов
/ 25 мая 2018

Вам нужно сгруппировать время по клиенту, а затем найти наименьший идентификатор клиента без временного интервала:

var timeSpaceFound = lstCustomerSlots.GroupBy(c => c.customerid)
                                     .Where(cg => !cg.Any(c => c.time == 3))
                                     .OrderBy(cg => cg.Key)
                                     .FirstOrDefault()
                                     ?.Key;

Я предпочитаю использовать метод расширения MinBy:

public static T MinBy<T, TKey>(this IEnumerable<T> src, Func<T,TKey> keySelector, Comparer<TKey> keyComparer) => src.Aggregate((a, b) => keyComparer.Compare(keySelector(a), keySelector(b)) < 0 ? a : b);
public static T MinBy<T, TKey>(this IEnumerable<T> src, Func<T,TKey> keySelector) => src.Aggregate((a, b) => Comparer<TKey>.Default.Compare(keySelector(a), keySelector(b)) < 0 ? a : b);

Тогда вы просто делаете

var timeSpaceFound = lstCustomerSlots.GroupBy(c => c.customerid)
                                     .Where(cg => !cg.Any(c => c.time == 4))
                                     .MinBy(cg => cg.Key)
                                     ?.Key;

Это должно быть более эффективным, поскольку Aggregate сделает только один проход по списку.

Если вы предпочитаете получать CustomerSlot вместо customerid вам нужно получить первое место в группе (если вам не нужен определенный временной интервал):

var timeSpaceFound = lstCustomerSlots.GroupBy(c => c.customerid)
                                     .Where(cg => !cg.Any(c => c.time == 4))
                                     .MinBy(cg => cg.Key)
                                     .FirstOrDefault();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...