Home > Mobile >  Get list of matching objects from 3 different lists
Get list of matching objects from 3 different lists

Time:06-01

I'm exercising on one task. Basically i got 3 different lists in C# code side. Class employee is containing the skills list. And also have list of employees as well.

for example :

class Employee
{
   List<Skills> Skills;
}

class Skills
{
   int Id;
   int Name;
}

class Where_Im_Working_Currently
{
   List<Employee> employees ;
}

What I'm trying to achieve is to get list of common skills from every individual. suppose we have 3 employees and all 3 employees have JAVA skill in common such that { id = x , name = JAVA }.

so all 3 employees have skills similar with id and name needs to be fetched out.

NOTE : I'm trying to get all matching skills and not just subset of skills

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

following is the query i have come up with :

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

but this will give IEnumerable that's where its getting wrong and im unable to form LINQ.

Any pointers or help are welcomed.

CodePudding user response:

This might not be the most optimized way of doing this, but here's a solution that outputs the skills that are common for all employees.

The key is to use SelectMany to get to the child lists.

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
}

If you uncomment the last Employee you would have a zero result, as there would no longer be a skill that is common for all employees.

Also you probably want to get distinct result, but it sounds like you already know how to do that.

Edit after original question was modified:

The below outputs only the skills that everyone has, if you uncomment the last Employee you would have null as result.

[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#
}
  • Related