c# - .NET :- 使用 linq 将对象与 Hashset 中的对象匹配
问题描述
目标是开发一个人力规划课程,根据员工的技能为他们分配工作。
我们有任务要在以下任务(变量)中分配。
IEnumerable<Task> task = repository.Tasks.ToList();
并且 taskSmall 包含 TaskId 和 Skill Id:-
Id SkillRequired
1 1
2 2
现在我们有人员列表
IEnumerable<Person> people = repository.People.ToList();
其中 people 包含诸如Person Name
,之类的字段HashSet<Skill> Skills
。一个人可以拥有多种技能。
问题是我们需要匹配任务所需的
task
技能和每个人的技能,HashSet
我们需要在分配后检索TaskId
和Person Name
分配。每项任务都需要一个人来执行。如果任务重复需要技能,那么我们需要根据技能检查哪个人不忙(或没有分配任何任务)来完成该任务。
解决方案
首先,我会扁平化,Person
Skills
以便每个人都有他们的一项技能:
var peopleSkill = people.SelectMany(p => p.Skills.Select(skill => new { skill, p }));
然后我会找到与任务所需技能相匹配的所有可能的人员集合,并按人员的技能数量排序,以便优先选择较少的技能人员进行分配:
var matchings = task.GroupJoin(peopleSkill,
t => t.SkillId,
ps => ps.skill.SkillId,
(task, pss) => new { task, people = pss.Select(ps => ps.p).OrderBy(p => p.Skills.Count) })
.OrderBy(tp => tp.people.Count());
然后,您可以完成可能的分配并将第一个可用的人分配给每个任务:
var assigned = new Dictionary<Task, Person>();
var usedPeople = new HashSet<Person>();
foreach (var m in matchings) {
foreach (var tryPerson in m.people) {
if (!usedPeople.Contains(tryPerson)) {
assigned.Add(m.task, tryPerson);
usedPeople.Add(tryPerson);
break;
}
}
}
这提供了IEnumerable
与 a 配对Person
或未null
分配的所有任务中的一个:
var ans = task.Select(t => new { task = t, person = assigned.TryGetValue(t, out var p) ? p : default });
推荐阅读
- c++ - 如何判断线程 A 的所有实例何时从线程 B 完成
- python - 在 python 中构建一个单词搜索生成器
- ios - Apple Music/Music Kit:如何获取歌曲 ID?
- python - 如何捕获有关 HDFS 上文件的信息
- azure-cosmosdb - Cosmos db - 如何在一个结果的特定属性中组合不同的结果值
- go - Go 模板不渲染
- typescript - 我的集成测试和我的 ORM 之间的日期差异
- sql-server - Azure - 创建免费 SQL 数据库需要哪些角色
- c# - 如何使用 httpwebresponse 获取网站名称
- c# - 无法为路由不同于 xyz.com/api/webhooks/incoming/* 的 asp.net 通用 webhook 设置 URI