How to Group By make Distinct from two Properties has same entity in C# Linq

你。 提交于 2019-12-12 03:32:18

问题


I'm having Two models Person and Boss. Boss is derived from Person. Here the property ID and SID both are speaking about the Employee ID. The ID Speaks about the Boss and SID speaks about the Assistant Staff.

Kindly refer the Model Classes and the Collection

public class Person
{
    public int ID { get; set; }
    public int SID { get; set; }
    public string Name { get; set; }
    public string Department { get; set; }
    public string Gender { get; set; }
    public string Role { get; set; }
}

public class Boss
{
    public int ID { get; set; }
    public int SID { get; set; }
    public string Name { get; set; }
    public string Department { get; set; }
    public string Gender { get; set; }
    public string Role { get; set; }
    public List<Person> Employees { get; set; }
}

void Main()
{

    List<Boss> BossList = new List<Boss>()
    {
        new Boss()
        {
            ID = 101,
            Name = "Harry",
            Department = "Development",
            Gender = "Male",
            Role = "Manager",
            Employees = new List<Person>()
            {
                new Person() {ID = 101, SID = 102, Name = "Peter", Department = "Development", Gender = "Male", Role = "Assistant"},
                new Person() {ID = 101, SID = 103, Name = "Emma Watson", Department = "Development", Gender = "Female", Role = "Assistant"},

            }
        },
        new Boss()
        {
            ID = 104,
            Name = "Raj",
            Department = "Development",
            Gender = "Male",
            Role = "Manager",
            Employees = new List<Person>()
                    {
                        new Person() {ID = 104, SID = 105, Name = "Kaliya", Department = "Development", Gender = "Male", Role = "Assistant"},
                        new Person() {ID = 104, SID = 103, Name = "Emma Watson", Department = "Development", Gender = "Female", Role = "Assistant"},

                    }
        },
        new Boss()
        {
            ID = 102,
            Name = "Peter",
            Department = "Development",
            Gender = "Male",
            Role = "Manager",
            Employees = new List<Person>()
                    {
                        new Person() {ID = 102, SID = 105, Name = "Kaliya", Department = "Development", Gender = "Male", Role = "Assistant"},
                        new Person() {ID = 102, SID = 103, Name = "Emma Watson", Department = "Development", Gender = "Female", Role = "Assistant"},

                    }
        }
    };
}

My Required Collection should be

List<Person> Members = new List<Person>()
    {
        new Person() {Name = "Harry", Department = "Development", Gender = "Male", Role = "Manager"},
        new Person() {Name = "Peter", Department = "Development", Gender = "Male", Role = "Manager"},
        new Person() {Name = "Emma Watson", Department = "Development", Gender = "Female", Role = "Assistant"},
        new Person() {Name = "Raj", Department = "Development", Gender = "Male", Role = "Manager"},
        new Person() {Name = "Kaliya", Department = "Development", Gender = "Male", Role = "Assistant"},
    }

Here My Requirement is I need to make the Distinct list of Employees including Boss. But the Distinct list contains Peter has an unique ID 102 in both Boss as well as in Assistant Staff, but here I need to select the Manager Role not a Assistant Role record.

Kindly assist me how to achieve this. Kindly provide your answer instead on suggestions to change the Model structure or any other suggestions.

Explanation of ID and SID:

  • ID : It has an Employee ID of Boss
  • SID : It has an Employee ID of Assistant

The Collection - Role is marked as Manager, then he/she don't have an SID, because he is a Boss (or) Manager. He/She is the Superior so the Employee ID is assigned in ID. In other case Role is marked as Assistant, then he/she is under any one of the Boss (or) Manager. So, the ID is marked with the Manager ID and the actual Employee ID is marked in SID.


回答1:


The first thing to do is to create custom IEqualityComparer<Person> class which will be used as Distinct argument.

Edit #2: taking into account role

public class PersonEqualityComparer : IEqualityComparer<Person>
{
    public bool Equals(Person x, Person y)
    {
        if(x == null && y == null) return true;
        int xid = x.Role == "Manager" ? x.ID : x.SID;
        int yid = y.Role == "Manager" ? y.ID : y.SID;
        return xid == yid;
    }

    public int GetHashCode(Person obj)
    {
        return obj.Role == "Manager" ? obj.ID : obj.SID;
    }
}

Then you can write this:

// take employees first
var personList = BossList.SelectMany(x => x.Employees).ToList();
// add bosses to list
personList.AddRange(BossList.AsEnumerable());
// take distinct persons
var result = personList.Distinct(new PersonEqualityComparer()).ToList();

I have noticed some issues with your code:

  1. SID = "Emma Watson" is used twice. I assume that something like SID = 103, Name = "Emma Watson" was intended.
  2. You've said that Boss is derived from Person, however code does not stick with this statement. I assume Boss : Person should be written and duplicate fields should be omitted.

Edit:

If it is possible kindly give your answer in a single inline LINQ Statement.

var result = BossList.SelectMany(x => x.Employees)
    .Union(BossList.AsEnumerable())
    .Distinct(new PersonEqualityComparer())
    .ToList();

Still you need to have PersonEqualityComparer code.


Edit #3

var personList = BossList.SelectMany(x => x.Employees).Union(BossList.AsEnumerable()).ToList();
var ids = personList.Select(x => x.Role == "Manager" ? x.ID : x.SID).Distinct().ToList();
var result = ids.GroupJoin(personList, id => id, person => person.Role == "Manager" ? person.ID : person.SID,
    (id, persons) => 
    persons.OrderBy(p => p.Role == "Manager" ? 0 : 1).First()).ToList();


来源:https://stackoverflow.com/questions/36068060/how-to-group-by-make-distinct-from-two-properties-has-same-entity-in-c-sharp-lin

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!