Linq выберите Distinct двумя свойствами

У меня довольно сложный запрос LINQ, который объединяет несколько таблиц и выбирает новый анонимный тип, который представляет собой три IEnumerable {Users, JobProviders, Jobs}. Он возвращает IQueryable для поддержания отложенного выполнения, что устраняет DistintBy из этого вопроса.

Один из столбцов - это ранг, и мне нужно убедиться, что выбрана только запись с самым низким рангом для каждого задания (другой столбец, многие задания будут выбраны). Различие не работает, потому что ранг, очевидно, сделает строку уникальной.

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

что-то вроде

let jobRank = JobProvider.Rank
...where min(rank)
2 ответа

Вы можете использовать группировку, так как это заставляет меня съеживаться, чтобы использовать groupBy, чтобы сделать отдельный. Вы можете просто вызвать First в IGrouping, чтобы получить один элемент из группы, что фактически является отдельным. Он будет выглядеть примерно так:

var distinctItems = data.GroupBy(item => new{
 //include all of the properties that you want to 
 //affect the distinct-ness of the query
 item.Property1
 item.Property2
 item.Property3
})
.Select(group => group.Key);
//if it important that you have the low rank use the one below.
// if you don't care use the line above
//.Select(group => group.Min(item => item.Rank));


Хорошее решение здесь:

LINQ's Distinct() для определенного свойства

Что вам нужно, это "отлично". Я не верю, что это часть LINQ, поскольку она довольно проста в написании:

What you need is a "distinct-by" effectively. I don't believe it part of LINQ as it stands, although it fairly easy to write:
public static IEnumerable<tsource> DistinctBy<tsource, tkey="">
 (this IEnumerable<tsource> source, Func<tsource, tkey=""> keySelector)
{
 HashSet<tkey> seenKeys = new HashSet<tkey>();
 foreach (TSource element in source)
 {
 if (seenKeys.Add(keySelector(element)))
 {
 yield return element;
 }
 }
}
</tkey></tkey></tsource,></tsource></tsource,></tsource>

licensed under cc by-sa 3.0 with attribution.