2014-11-21 2 views
0

У меня есть статический набор категорий и входящий список элементов, которые находятся в разных категориях. Я хочу получить первый элемент, который соответствует лучшей категории, и если ни один не найден, получите первый элемент, который соответствует следующей лучшей категории, и т. Д., Пока я не получу категорию по умолчанию.Запрос LINQ для поиска нескольких условий в определенном порядке?

Я попытался поместить свои категории в IEnumerable и сделать на нем Contains(), чтобы увидеть, соответствуют ли входящие элементы категории, и останавливаются в первом матче. Но я не могу контролировать порядок соответствия: если список категорий упорядочен по приоритету [best, OK, default], первый элемент ввода соответствует что-либо в списке категорий. Поэтому, если мой первый элемент ввода соответствует OK, а второй элемент ввода соответствует Best, тогда я остановлюсь, прежде чем я получу Best.

Прямо сейчас я запустил Where() над списком элементов, а если результат равен нулю, я запустил второй Where() и т. Д. Я хотел бы знать, есть ли более сжатый (или более LINQ-идиоматический) способ написать это :

public MyVM getVM(IEnumerable<Entities.Foo> foos) 
    { 
     Entities.Foo foo = null; 
     MyVM   myVM = null; 

     if (entity.IsBar) 
     { 
      foo = foos.Where(f => f.FooCatId == FooCategories.BestCat).FirstOrDefault(); 
     } 

     // no foos are BestCat, look for OkCat 
     if (foo == null) 
     { 
      foo = foos.Where(f => f.FooCatId == FooCategories.OkCat).FirstOrDefault(); 
     } 

     // no foos are OkCat, look for DefaultCat 
     if (foo == null) 
     { 
      foo = foos.Where(f => f.FooCatId == FooCategories.DefaultCat).FirstOrDefault(); 
     } 

     if (foo != null) 
     { 
      myVM = new MyVM() { Name = foo.Name }; 
     } 
     return myVM; 
    } 

    public enum FooCategories 
    { 
     DefaultCat, 
     SomeCat, 
     AnotherCat, 
     OkCat, 
     BestCat, 
     BadCat 
    } 

ответ

4

Там, безусловно, более краткий способ сделать это, двумя способами:

  • Использовать перегрузку FirstOrDefault, которая принимает предикат
  • Используйте нуль-коалесцирующий оператор

Я буду игнорировать ваши IsBar чек на данный момент, потому что я не понимаю, как это вписывается в ... но все остальное было бы:

var foo = foos.FirstOrDefault(f => f.FooCatId == FooCategories.BestCat) 
     ?? foos.FirstOrDefault(f => f.FooCatId == FooCategories.OkCat) 
     ?? foos.FirstOrDefault(f => f.FooCatId == FooCategories.DefaultCat); 

Другим вариантом было бы изменение ваш порядок перечисления, чтобы вы могли просто найти кота с лучшей категорией - либо с помощью OrderByDescending(f => f.FooCatId), либо с помощью MaxBy от MoreLINQ. Вам также нужно будет проверить, что результирующая кошка не плохая кошка и т. Д., Поэтому она может быть не очень выигрышной, но MaxBy будет, по крайней мере, более эффективен, пройдя только один раз.

+0

D'oh, я забыл о перегрузке предиката для FirstOrDefault! Я попробовал оператор с нулевым коалесцированием, но мои предикаты были в предыдущем предложении Where, и это не сработало. Не беспокойтесь о IsBar - я пропустил это при анонимной мой код; это просто условие для получения предпочтительной категории. В этом случае я не могу изменить порядок входящего списка, но я могу изменить порядок перечислений, поэтому я тоже буду играть с этим, но, как вы говорите, я не думаю, что к тому времени, когда я занимаюсь здравым смыслом, чеки. Спасибо за советы - очень честь получить от вас ответ! – Val

Смежные вопросы