Как ввести ключевое слово Let внутри инструкции Linq с помощью Group by

#c# #.net #linq #group-by

#c# #.net #linq #group-by

Вопрос:

У меня есть следующий оператор Linq с предложением ‘Group by’, и я хотел бы знать, как ввести let или любой другой оператор, чтобы избежать повторения подзапроса, lifecycleEvents.Where(i => i.LifecycleEventId == grouping.Key).First() в следующем примере

 var completionTimeModels =
    from timeline in processTimelines 
    group timeline by timeline.LifecycleEventId into grouping
    select new CompletionTimeViewModel()
    {
        // How to avoid repeating the same query to find the life cycle event?
        Name = lifecycleEvents.Where(i => i.LifecycleEventId == grouping.Key).First().LifecycleEventName,
        DisplayName = lifecycleEvents.Where(i => i.LifecycleEventId == grouping.Key).First().LifecycleEventDisplayName
    };
  

Ответ №1:

 var completionTimeModels =
from timeline in processTimelines

group timeline by timeline.LifecycleEventId into grouping
let foo = lifecycleEvents.First(i => i.LifecycleEventId == grouping.Key)
select new CompletionTimeViewModel()
{
    Name = foo.LifecycleEventName,
    DisplayName = foo.LifecycleEventDisplayName
};
  

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

1. Все эти ответы идентичны. Это действительно довольно просто.

2. Используйте First(i => i.LifecycleEventId == grouping.Key)

3. поскольку идентификаторы lifecycleeventid различны, у нас может быть несколько ключей группировки, поэтому какой ключ будет участвовать в запросе как grouping.Key?

4. @amesh, из-за группировки каждый элемент в группе будет иметь один и тот же ключ. Затем мы выбираем один элемент из lifecycleEvents для каждой группы на основе ключа группы. Первый вызов выполняется один раз для каждой группы.

5. Вызов Group возвращает IEnumerable of groups, который повторяется в вызове select, который также вызывает . Сначала один раз для каждой группы. Вызов .First выполняется один раз для каждой группы, сам по себе он не выполняет итерацию по всем группам.

Ответ №2:

 var completionTimeModels =
    from timeline in processTimelines
    group timeline by timeline.LifecycleEventId into grouping
    let lifecyleEvent = lifecycleEvents.Where(i => i.LifecycleEventId == grouping.Key).First()
    select new CompletionTimeViewModel()
    {
        Name = lifecyleEvent.LifecycleEventName,
        DisplayName = lifecyleEvent.LifecycleEventDisplayName
    };
  

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

1. Используйте First(i => i.LifecycleEventId == grouping.Key)

2. @abatishchev: Абсолютно. Я удивлен, что сам этого не понял. Передача предикатов методам расширения, отличным от Where, является одним из моих любимых недооцененных / недостаточно используемых методов linq.

Ответ №3:

 var completionTimeModels =
    from timeline in processTimelines 
    group timeline by timeline.LifecycleEventId into grouping
    let current = lifecycleEvents.Where(i => i.LifecycleEventId == grouping.Key).First()
    select new CompletionTimeViewModel()
    {
            // How to avoid repeating the same query to find the life cycle event?
        Name = current.LifecycleEventName,
        DisplayName = current.LifecycleEventDisplayName
    };
  

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

1. Используйте First(i => i.LifecycleEventId == grouping.Key)

Ответ №4:

 var completionTimeModels =
    from timeline in processTimelines 
    group timeline by timeline.LifecycleEventId into grouping
    let lifecyleEvent = lifecycleEvents.First(i => i.LifecycleEventId == grouping.Key)
    select new CompletionTimeViewModel()
    {
        // How to avoid repeating the same query to find the life cycle event?
        Name = lifecyleEvent.LifecycleEventName
        DisplayName = lifecyleEvent.LifecycleEventDisplayName
    };