По сути, мне нужно сохранить одну строку, выбирая строки, в которых значение selectorCol не равно нулю ИЛИ не первое.
Вы прямо не сказали этого, но я предполагаю, что если две строки имеют одинаковые Col1
, то они также имеют одинаковые Col2
и Col3
Требование Учитывая последовательность MyRows
, создайте результирующую последовательность, созданную из групп MyRows
с тем же значением для Col1
. Из каждой группы я хочу, чтобы первый элемент имел ненулевое значение SelectorCol
Если вы напишите требование точно, это не кажется очень сложным. Единственная проблема: что такое первый элемент группы ? Это самый низкий индекс?
Поскольку GroupBy ничего не гарантирует в отношении сохранения первоначального заказа, мы должны помнить индекс оригинальных предметов.
- Выберите, где вы помните индекс исходного элемента
- Затем создайте группы элементов с одинаковым значением для
Col1
- Из каждой группы сохраните элементы, которые имеют ненулевое значение для SelectorCol
- Затем возьмите тот, у которого самый низкий индекс.
.
// first remember the original index
var result = myRows.Select( (row, index) => new
{
Index = index
Row = row,
}
// Then make groups of rows with same value for Col1
.GroupBy(selectResult => selectResult.Row.Col1,
// Parameter resultSelector: get the key of each group (= common Col1 value)
// and all rows that have this Col1 value
// keep only the groupElements that have a non-null value for SelectorCol
(col1, rowsWithThisCol1) => rows.WithThisCol1
.Where(groupElement => groupElement.Row.SelectorCol != null)
// from the remaining rows, keep the one with the lowest index
.OrderBy(groupElement => groupElement.Index)
// we don't need the Index anymore, select only the Row
.Select(groupElement => groupElement.Row)
// and keep the first:
.FirstOrDefault();
Несмотря на то, что это работает, упорядочивать все элементы группы, если вам нужен только элемент с наименьшим индексом, - пустая трата времени. Используйте Aggregate, если вы хотите перечислить только один раз. Так что вместо OrderBy:
.Aggregate((groupElementWithLowestIndex, groupElement) =>
// if the index of groupElement is lower,
// then that element becomes the one with the lowest index
(groupElement.Index < groupElementWithLowestIndex.Index) ?
groupElement : groupElementWithLowestIndex)
// result: the one and only groupElement with the lowest index
// note: you are certain that no group is empty! So there is always one with lowest index
// get rid of the index, keep only the Row
.Row;