Найти совпадающие идентификаторы между двумя различными объектами списка только при наличии всех идентификаторов или более? - PullRequest
0 голосов
/ 26 декабря 2018

У меня проблемы с поиском подходящих значений между двумя отдельными объектами List.Цель состоит в том, чтобы определить, имеет ли определенный сотрудник ВСЕ или более необходимых навыков для выполнения работы.

Объекты List выглядят следующим образом:

EmployeeSkills.cs

public int EMP_SKILL_ID { get; set; }
public int EMP_ID { get; set; }
public int SKILL_ID { get; set; }

SkillsRequired.cs

public int SKILL_REQ_ID { get; set; }
public int JOB_ID { get; set; }
public int SKILL_ID { get; set; }

Я пытался использовать Linq, чтобы найтибез совпадений, я также попробовал вложенный цикл foreach, который находит все навыки, которые есть у пользователя, но после этого я не уверен, как определить, обладают ли они ВСЕМИ необходимыми навыками.

var matches = new List<int>();

foreach (var employee in employeeSkills)
{
    foreach (var skills in skillsRequired)
    {
        if (employee.SKILL_ID == skills.SKILL_ID)
        {
            matches.Add(employee.SKILL_ID);
            matches.Add(skills.JOB_ID);
            matches.Add(employee.SKILL_ID);
        }
    }
}

Списки EmployeeSkills и SkillsRequired выглядят примерно так:

+--------------+--------+----------+
| EMP_SKILL_ID | EMP_ID | SKILL_ID |
+--------------+--------+----------+
|            1 |      1 |        1 |
|            2 |      1 |        2 |
|            3 |      1 |        3 |
|            4 |      2 |        1 |
|            5 |      2 |        2 |
|            6 |      2 |        4 |
+--------------+--------+----------+
+--------------+--------+----------+
| SKILL_REQ_ID | JOB_ID | SKILL_ID |
+--------------+--------+----------+
|            1 |      1 |        1 |
|            2 |      1 |        2 |
|            3 |      1 |        3 |
|            4 |      2 |        1 |
|            5 |      2 |        2 |
|            6 |      2 |        4 |
|            7 |      2 |        5 |
+--------------+--------+----------+

Каждый сотрудник нуждается в правильных навыках для работы.EMP_ID 1 может завершить JOB_ID 1, но никто не обладает всеми навыками, необходимыми для завершения JOB_ID 2.

Есть ли способ выбрать все задания на основе того, есть ли у пользователя все или более SKILL_ID, необходимых для задания.

Ответы [ 3 ]

0 голосов
/ 26 декабря 2018

Попробуйте следующий код, который не требует пояснений.Я использовал словарь, чтобы сделать код максимально простым

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<EmployeeSkills> employeeSkills = new List<EmployeeSkills>() {
                new EmployeeSkills() { EMP_SKILL_ID = 1, EMP_ID = 1, SKILL_ID = 1},
                new EmployeeSkills() { EMP_SKILL_ID = 2, EMP_ID = 1, SKILL_ID = 2},
                new EmployeeSkills() { EMP_SKILL_ID = 3, EMP_ID = 1, SKILL_ID = 3},
                new EmployeeSkills() { EMP_SKILL_ID = 4, EMP_ID = 2, SKILL_ID = 1},
                new EmployeeSkills() { EMP_SKILL_ID = 5, EMP_ID = 2, SKILL_ID = 2},
                new EmployeeSkills() { EMP_SKILL_ID = 6, EMP_ID = 2, SKILL_ID = 4}
            };

            List<SkillsRequired> skillsRequired = new List<SkillsRequired>() {
                new SkillsRequired() { SKILL_REQ_ID = 1, JOB_ID = 1, SKILL_ID = 1},
                new SkillsRequired() { SKILL_REQ_ID = 2, JOB_ID = 1, SKILL_ID = 2},
                new SkillsRequired() { SKILL_REQ_ID = 3, JOB_ID = 1, SKILL_ID = 3},
                new SkillsRequired() { SKILL_REQ_ID = 4, JOB_ID = 2, SKILL_ID = 1},
                new SkillsRequired() { SKILL_REQ_ID = 5, JOB_ID = 2, SKILL_ID = 2},
                new SkillsRequired() { SKILL_REQ_ID = 6, JOB_ID = 2, SKILL_ID = 4},
                new SkillsRequired() { SKILL_REQ_ID = 7, JOB_ID = 2, SKILL_ID = 5}
            };

            var skills_employees = (from s in skillsRequired
                                    join e in employeeSkills on s.SKILL_ID equals e.SKILL_ID
                                    select new { skill_required_id = s.SKILL_REQ_ID, job_id = s.JOB_ID, skill_id = s.SKILL_ID, emp_skill_id = e.EMP_SKILL_ID, emp_id = e.EMP_ID }
                                    ).ToList();

            Dictionary<int, List<int>> job_skills = skillsRequired.GroupBy(x => x.JOB_ID, y => y.SKILL_ID)
                .ToDictionary(x => x.Key, y => y.ToList());

            var groups = skills_employees.GroupBy(x => new { employee = x.emp_id, job_id = x.job_id }).Select(x => new { employee = x.Key.employee, job_id = x.Key.job_id, skills = x.Select(y => y.skill_id).ToList() }).ToList();


            var results = groups.Select(x => new { employee_id = x.employee, job_id = x.job_id, qualifed = job_skills[x.job_id].All(y => x.skills.Contains(y)) ? "qualified" : "not qualified" }).ToList(); 


        }
    }
    public class EmployeeSkills
    {
        public int EMP_SKILL_ID { get; set; }
        public int EMP_ID { get; set; }
        public int SKILL_ID { get; set; }
    }
    public class SkillsRequired
    {
        public int SKILL_REQ_ID { get; set; }
        public int JOB_ID { get; set; }
        public int SKILL_ID { get; set; }
    }
}
0 голосов
/ 27 декабря 2018

Вот довольно подробное решение вашей проблемы:

var matches = new Dictionary<int, List<int>>();

var employees = employeeSkills.ToLookup(emp => emp.EMP_ID, skill => skill.SKILL_ID);
var jobs = skillsRequired.GroupBy(skill => skill.JOB_ID, skill => skill.SKILL_ID);

foreach (var job in jobs)
{
    var capableEmployees = new List<int>();

    foreach (var employee in employees)
    {
        bool isCapable = true;

        foreach (int requiredSkill in job)
        {
            bool hasRequiredSkill = false;

            foreach (int skill in employee)
            {
                if (skill == requiredSkill)
                {
                    hasRequiredSkill = true;
                    break;
                }
            }

            if (!hasRequiredSkill)
            {
                isCapable = false;
                break;
            }
        }

        if (isCapable)
        {
            capableEmployees.Add(employee.Key);
        }
    }

    matches.Add(job.Key, capableEmployees);
}

Как только вы поняли это и узнали какой-то LINQ, вы можете легко превратить его в следующее:

var matches = new Dictionary<int, List<int>>();

var employees = employeeSkills.ToLookup(emp => emp.EMP_ID, skill => skill.SKILL_ID);
var jobs = skillsRequired.GroupBy(skill => skill.JOB_ID, skill => skill.SKILL_ID);

foreach (var job in jobs)
{
    var capableEmployees = (from employee in employees
                            where job.All(required => employee.Any(skill => skill == required))
                            select employee.Key).ToList();

    matches.Add(job.Key, capableEmployees);
}

Или дажеthis:

var employees = employeeSkills.ToLookup(emp => emp.EMP_ID, skill => skill.SKILL_ID);
var matches = skillsRequired.GroupBy(skill => skill.JOB_ID, skill => skill.SKILL_ID)
                            .ToDictionary(job => job.Key,
                                          job => employees.Where(emp => job.All(required => emp.Any(skill => skill == required)))
                                                          .Select(emp => emp.Key).ToList());

Все три решения эквивалентны и дают одинаковый результат.

Обратите внимание на использование метода ToLookup для группировки employeeSkills.ToLookup очень похож на GroupBy за исключением того, что он оценивается немедленно.Это означает, что перечисление employeeSkills группируется только один раз, а не один раз для каждого задания.

0 голосов
/ 26 декабря 2018

Есть несколько способов сделать это, особенно это удобно с LINQ.

Например, это гарантирует, что сотрудник обладает всеми навыками в списке skillsRequired:

skillsRequired.All(f => employeeSkills.Any(v => v.SKILL_ID == f.SKILL_ID));

Или вы можете проверить, не пропускает ли сотрудник какие-либо навыки:

var requiredSkillIDs = skillsRequired.Select(f => f.SKILL_ID);
var employeeSkillIDs = employeeSkills.Select(f => f.SKILL_ID);
var missingSkillIDs = requiredSkillIDs.Except(employeeSkillsIDs);

Таким образом, вы можете уведомить пользователя о пропущенных навыках.

Я очень рекомендуюВы посмотрите на документы на LINQ , это очень полезно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...