我在如何查找两个单独的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);
}
}
}
“员工技能和技能要求”列表看起来像这样。
+--------------+--------+----------+
| 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来选择所有作业。
答案 0 :(得分:1)
有很多方法可以做到这一点,这对于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);
这样,您可以通知用户缺少的技能。
强烈建议您看看docs on LINQ,它非常有用。
答案 1 :(得分:1)
以下是您问题的详细解决方案:
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);
}
甚至是这样:
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
枚举仅被分组一次,而不是每个作业一次。
答案 2 :(得分:-1)
请尝试下面的代码,这些代码是不言自明的。我用字典使代码尽可能简单
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; }
}
}