【问题标题】:How to Group By make Distinct from two Properties has same entity in C# Linq如何在 C# Linq 中通过区分两个属性进行分组具有相同的实体
【发布时间】:2016-03-17 17:47:30
【问题描述】:

我有两个模型 Person 和 Boss。 Boss 源自 Person。这里的属性 ID 和 SID 都在谈论 Employee ID。 ID 谈老板,SID 谈助理职员。

请参考模型类和集合

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

                    }
        }
    };
}

我需要的收藏应该是

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

这里我的要求是我需要制作包括老板在内的不同员工名单。但是 Distinct 列表包含 Peter 在 Boss 和 Assistant Staff 中都有一个 unique ID 102,但在这里我需要选择 Manager Role 而不是 Assistant Role 记录。

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

ID和SID说明:

  • ID : Employee ID 为 Boss
  • SID : 员工 ID 为 Assistant

集合 - 角色被标记为经理,然后他/她没有 SID,因为他是老板(或)经理。他/她是上级,因此在 ID 中分配了员工 ID。在其他情况下,角色被标记为助理,则他/她在任何一位老板(或)经理之下。因此,ID 标记为 Manager ID,而实际的 Employee ID 标记为 SID。

【问题讨论】:

  • 我无法理解,但我尝试了 linq BossList.GroupBy(i => i.ID).Select(j => j.FirstOrDefault()).ToList() ;
  • 你能解释一下ID和SID吗?
  • 您的代码甚至无法编译。 SID = "Emma Watson"?让它起作用。并使其更简短,更清楚您的要求:P
  • 我在帖子中添加了其他注释。请刷新并再次阅读。
  • 我创建了一个类库,它有一个 LINQ 扩展方法,可以用于此(用于内存中的集合)。它被称为Linqy,可在 Nuget 上使用。要在这里使用它,你会做.DistinctBy(p =&gt; p.Role ==" Manager" ? p.ID : p.SID)

标签: c# linq distinct


【解决方案1】:

首先要做的是创建自定义IEqualityComparer&lt;Person&gt; 类,该类将用作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 并且应该省略重复的字段。

编辑:

如果可能,请在单个内联 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();

【讨论】:

  • 如果可能,请在单个内联 LINQ 语句中给出您的答案。
  • 你能检查一下角色吗?
  • 我更正了 Emma Watson 的 SID
  • @B.Balamanigandan,edit#3 给出的输出中有什么不正确的?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-05
  • 2018-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多