如何分组依据两个属性在C#Linq中具有相同的实体

时间:2016-03-17 17:47:30

标签: c# linq distinct

我有两个模特人物和老板。老板来自人。这里的属性ID和SID都是关于员工ID的。关于Boss和SID的身份证谈及助理员工。

请参阅模型类和集合

lon

My Required 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"},

                    }
        }
    };
}

这里我的要求是我需要制作包括Boss在内的员工队伍。但是,包含 Peter Peter 在Boss和Assistant Staff中都有唯一ID 102 ,但在这里我需要选择Manager Role而不是Assistant Role记录。

请帮助我如何实现这一目标。请提供您的答案,而不是改变模型结构或任何其他建议的建议。

ID和SID的说明:

  • ID :员工ID为Boss
  • SID :其员工ID为助理

收藏 - 角色被标记为经理,然后他/她没有SID,因为他是老板(或)经理。他/她是高级人员,因此员工ID以ID分配。在其他情况下,角色被标记为助理,然后他/她在任何一个Boss(或)经理之下。因此,ID标记有Manager ID,实际的Employee ID标记为SID。

1 个答案:

答案 0 :(得分:2)

要做的第一件事是创建自定义IEqualityComparer<Person>类,该类将用作Distinct参数。

编辑#2 :考虑角色

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;
    }
}

然后你可以这样写:

// 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();

我注意到您的代码存在一些问题:

  1. SID = "Emma Watson"使用了两次。我假设有SID = 103, Name = "Emma Watson"之类的内容。
  2. 你说过Boss是派生于Person的,但是代码并没有坚持这个陈述。我假设应该写Boss : Person并且应该省略重复的字段。
  3. 修改

      

    如果有可能,请在单个内联LINQ声明中给出答案。

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

    仍然需要PersonEqualityComparer代码。

    编辑#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();