Объекты Linq GroupBy с условием if else

#c# #linq

#c# #linq

Вопрос:

Я новичок в c # linq и борюсь с чем-то. У меня есть список, и я хочу собрать из него конкретную информацию, как в следующем примере:

Допустим, у меня есть следующий список kidsEat объектов:

 {NAME=joseph, FOOD=banana, EATEN=true}
 
{NAME=joseph, FOOD=apple, EATEN=false}

{NAME=billy, FOOD=banana, EATEN=false}

{NAME=billy, FOOD=apple, EATEN=false}
 

Из этого списка я хочу знать для каждого из мальчиков, ел ли он что-нибудь или нет.

Если он действительно что-то съел, он возьмет предмет, на котором написано, что он съел.

Если он не поел, потребуется один случайный объект, где он не поел.

Итак, этот пример должен возвращать список следующих 2 объектов:

 {NAME=joseph, FOOD=banana, EATEN=true}

{NAME=billy, FOOD=banana, EATEN=false}     //banana could be switched to apple, it doesn't matter
 

Итак. Я подумал о чем-то вроде:

 KidsList.GroupBy(kid=>kid.NAME).Where().Select(kid=>kid.First())
 

Но я не знаю, что вставить в предложение where, потому что это все равно, что перебирать все строки, затем находить, является ли одна из них истинной, и если да, то ставить «true», а затем ставить false. Такое ощущение, что ему нужно какое-то if else внутри запроса LINQ.

Любая помощь?

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

1. Не используйте заглавные буквы для имен свойств; используйте регистр Pascal, например Name , Food , Eaten или SomethingElse и т. Д.

Ответ №1:

Выберите либо первую «съеденную» запись, либо первую «не съеденную» запись, если нет «съеденных» записей

 KidsList.GroupBy(k => k.NAME)
  .Select(g => g.FirstOrDefault(k => k.EATEN) ?? g.First())
 

Объяснение: Если нет записей, соответствующих k => k.EATEN предикату, then FirstOrDefault вернет значение по умолчанию, которое равно null . В этом случае оператор объединения с нулем ?? вычислит правый операнд и вернет First запись (которая, очевидно, будет «не съедена»).

Ответ №2:

Вы можете упорядочить элементы группы по EATEN , а затем выбрать первый элемент:

 var ans = src.GroupBy(e => e.NAME)
             .Select(eg => eg.OrderByDescending(e => e.EATEN).First());
 

Ответ №3:

Требование:

Из этого списка я хочу знать для каждого из мальчиков, съел ли он что-нибудь или нет. Если он что-то съел, он получит объект, который говорит, что он съел. Если он не поел, потребуется один случайный объект, где он не поел.

Что, если один из мальчиков съел больше одного предмета? Что это значит: «возьмите объект, который говорит, что он съел»?
Итак, давайте изменим это на: «Возьмите любой из объектов, которые он съел».
Если вы уверены, что никто не съел больше одного элемента, то разницы нет.

Для этого вам не нужен Where .

Сначала вам нужно знать для каждого ребенка объекты, которые он съел и не съел. Упорядочите это по убыванию значения для съеденного: сначала продукты, которые были съедены (=true), затем продукты, которые не были съедены (=false). Из этой последовательности продуктов возьмите первый элемент.

Если ребенок съел хотя бы одну вещь, то первым предметом будет съеденный предмет. Если он ничего не съел (= если все вхождения Съеденного были ложными), то первый элемент будет не съеденным элементом.

Мы будем использовать перегрузку Enumerable .GroupBy, у которого есть параметр resultSelector . В resultSelector мы сделаем OrderByDescending значение Eaten, как описано выше. Затем мы выберем первое питание.

 IEnumerable<KidsEat> kidsEats = ...
var result = kidsEats.GroupBy(kid => kid.Name,

    // parameter resultSelector: for every kid's Name, and all kidsEats with this Name
    // make one new object:
    (name, kidsEatsWithThisName) => new
    {
        Name = name,
        Food = kidsEatsWithThisName
               .OrderByDescending(kidsEat => kidsEat.Eaten)
               .Select(kidsEat => kidsEat.Food)
               .FirstOrDefault(),
    });
 

Словами: из последовательности детских мест создайте группы детских мест с одинаковыми именами. Из каждой группы создайте один новый объект со свойствами Name и Food следующим образом:

  • Значение свойства Name — это ключ группы, который является общим именем всех детских мест в этой группе.
  • Чтобы вычислить значение свойства Food , упорядочьте все детские места в группе (= все детские места с этим именем) по убыванию значения съеденного свойства: сначала истинные значения, затем ложные значения.
  • Из этой упорядоченной последовательности детских мест берется стоимость имущества Food. Результат: последовательность продуктов, сначала продукты, которые ел ребенок с таким именем, затем продукты, которые не ел этот ребенок.
  • Из этой последовательности Продуктов возьмите первый пункт. Если этот ребенок ничего не ел, то первый пункт — это недоеденная Пища. Если он что-то съел, то этот первый предмет — Съеденная Пища.

Simple comme bonjour! (как только вы узнаете, как это сделать)

Ответ №4:

Одним из способов было бы использовать Aggregate функцию.

 list.GroupBy(k => k.NAME)
  .Select(g => g.Aggregate ((x, y) => x.EATEN amp;amp; !y.EATEN ? x : y))