首页 > 解决方案 > .NET :- 使用 linq 将对象与 Hashset 中的对象匹配

问题描述

目标是开发一个人力规划课程,根据员工的技能为他们分配工作。

并且 taskSmall 包含 TaskId 和 Skill Id:-

Id  SkillRequired
1   1
2   2

其中 people 包含诸如Person Name,之类的字段HashSet<Skill> Skills。一个人可以拥有多种技能。

标签: c#asp.net.netasp.net-mvclinq

解决方案


首先,我会扁平化,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 });

推荐阅读