从 3 个不同的列表中获取匹配对象的列表

Get list of matching objects from 3 different lists

我正在锻炼一项任务。基本上我在 C# 代码端得到了 3 个不同的列表。 Class 员工包含技能列表。还有员工名单。

例如:

class Employee
{
   List<Skills> Skills;
}

class Skills
{
   int Id;
   int Name;
}

class Where_Im_Working_Currently
{
   List<Employee> employees ;
}

我想要实现的是从每个人那里获得共同技能的列表。假设我们有 3 名员工,所有 3 名员工都有 JAVA 共同技能,例如 { id = x , name = JAVA }.

因此3名员工的技能都相似,需要提取id和name。

注意:我正在尝试获得所有匹配技能,而不仅仅是技能的子集

for e.g. 
    Case 1: Perfect match. (Get List having a, b, c)
         list 1 =>  a, b, c
         list 2 =>  a, b, c
         list 3 =>  a, b, c

    Case 1: No match. (Get Null list)
         list 1 =>  a, b, c
         list 2 =>  a, b,
         list 3 =>  b, c

以下是我提出的查询:

var skills= employees.Select(x => x.Skills.Select(p => p.Id== x.Skill[0].Id && p.Name == x.Skill[0].Name));

但这会给 IEnumerable 带来错误,我无法形成 LINQ。

欢迎任何指点或帮助。

这可能不是最优化的方法,但这里有一个解决方案,可以输出所有员工共有的技能。

关键是使用 SelectMany 获取子列表。

public class Employee
{
    public List<Skills> Skills { get; set; }
}

public class Skills
{
    public int Id { get; set; }
    public string Name { get; set; }
}

[Test]
public void GetSomeSkills()
{
    var employees = new List<Employee>
    {
        new Employee { Skills = new List<Skills> { new Skills { Id = 1, Name = "Java" }, new Skills { Id = 2, Name = "C#" } } },
        new Employee { Skills = new List<Skills> { new Skills { Id = 1, Name = "Java" }, new Skills { Id = 3, Name = "Cooking" } } },
        new Employee { Skills = new List<Skills> { new Skills { Id = 1, Name = "Java" } } },
        //new Employee { Skills = new List<Skills> { new Skills { Id = 4, Name = "C++" } } }
    };

    var allSkills = employees.SelectMany(x => x.Skills).ToList();
    
    Console.WriteLine(string.Join(", ", allSkills.Select(x => x.Name)));
    // Output: Java, C#, Java, Cooking, Java

    var commonSkills = employees.SelectMany(e =>
        e.Skills.Where(s => employees.All(e2 => e2.Skills.Select(x => x.Id).Contains(s.Id)))).ToList();

    Console.WriteLine(string.Join(", ", commonSkills.Select(x => x.Name)));
    // Output: Java, Java, Java
}

如果您取消对最后一位员工的注释,您的结果将为零,因为不再有一项对所有员工都通用的技能。

您可能还想获得不同的结果,但听起来您已经知道该怎么做。

修改原始问题后编辑:

下面只输出每个人都拥有的技能,如果你取消注释最后一个 Employee,结果将是 null。

[Test]
public void GetSomeSkills()
{
    var employees = new List<Employee>
    {
        new Employee { Skills = new List<Skills> { new Skills { Id = 1, Name = "Java" }, new Skills { Id = 2, Name = "C#" } } },
        new Employee { Skills = new List<Skills> { new Skills { Id = 1, Name = "Java" }, new Skills { Id = 2, Name = "C#" } } },
        // new Employee { Skills = new List<Skills> { new Skills { Id = 1, Name = "Java" } } },
    };

    bool HasSameSkills(Employee first, Employee second)
    {
        var firstIds = first.Skills.Select(x => x.Id).OrderBy(x => x).ToList();
        var secondIds = second.Skills.Select(x => x.Id).OrderBy(x => x).ToList();
        return firstIds.SequenceEqual(secondIds);
    }

    var commonSkills = employees.FirstOrDefault(x => employees.All(y => HasSameSkills(x, y)))?.Skills;

    Console.WriteLine(string.Join(", ", (commonSkills ?? new List<Skills>()).Select(x => x.Name)));
    // Output: Java, C#
}