Запросы Linq для двух коллекций

185
04 апреля 2019, 02:30

Есть два класса:

class Employees
{
    public string Surname { get; set; }
    public string Position { get; set; }
    public string Department { get; set; }
    public int Age { get; set; }
}

и

class Salaryes
{
    public string Position { get; set; }
    public decimal Salary { get; set; }
}

Созданы две коллекции List<>. Помогите пожалуйста сделать Linq-выборку для определения отдела с максимальной средней зарплатой

var maxAverageQuery = listEmployees.GroupBy(list => list.Department).Select(gr => new { gr.Key, Sum = listSalaryes.Where(list2=>listEmployees.Select(list=>list.Position).ToString()==list2.Position).Average(lis => lis.Salary) })
Answer 1

Примерно так:

var employees = new List<Employees>(...);
var salaryes = new List<Salaryes>(...);
var ExpensiveDepartment = employees
    // Соединяем сотрудников и позиции,
    //  выбираем в итоговую выборку наименование отдела и зарплату сотрудника
    .Join(salaryes, e => e.Position, s => s.Position, (e, s) => new { e.Department, s.Salary })
    // Группируем по отделам
    .GroupBy(a => a.Department, a => a.Salary)
    // Находим для каждого отдела среднюю зарплату
    .Select(g => new { Department = g.Key, AvgSalary = g.Average() })
    // Сортируем по средней зарплате
    .OrderByDescending(a => a.AvgSalary)
    // Берем самое большое значение средней зарплаты
    .First()
    // Берем наименование отдела
    .Department;

Но на самом деле вы как-то странно организовали иерархию классов, во-первых, почему названия классов во множественном числе? Это ведь один экземпляр (если у вас EF или типа того, не переживайте, он сам разберется как ему именовать таблицы), во-вторых, почему бы не хранить в сотруднике ссылку на его должность? Итого:

class Employee
{
    public string Surname { get; set; }
    public Position Position { get; set; }
    public string Department { get; set; }
    public int Age { get; set; }
}
class Position
{
    public string Name { get; set; }
    public decimal Salary { get; set; }
}

И потом всё становится несколько проще:

var employees = new List<Employee>(...);
var salaryes = new List<Position>(...);
var ExpensiveDepartment = employees
    .GroupBy(e => e.Department)
    .Select(g => new { Department = g.Key, AvgSalary = g.Average(e => e.Position.Salary) })
    .OrderByDescending(a => a.AvgSalary)
    .First()
    .Department;
READ ALSO
Как создать такой массив кодом?

Как создать такой массив кодом?

Хочу создать такой массив программноСпасибо

158
ITEXT7: Как создать абзац смешивая различные шрифты?

ITEXT7: Как создать абзац смешивая различные шрифты?

Я использовал iText 7 в течение нескольких дней для создания pdf файлов и могу сказать, что он, к сожалению, сильно отличается от iText 5 и документация...

194
Как сделать рандомный рандом в C# [дубликат]

Как сделать рандомный рандом в C# [дубликат]

На данный вопрос уже ответили:

187
C# 8.0 Caller Argument Expression

C# 8.0 Caller Argument Expression

Наткнулся на вот эту статью, которая посвящена фишкам, которые с высокой вероятностью будут добавлены в новую версию языка

130