【问题标题】:LINQ and removing duplicates from an array of objectsLINQ 并从对象数组中删除重复项
【发布时间】:2015-02-09 00:47:17
【问题描述】:

我正在尝试使用两列对对象数组进行重复数据删除,其中第二列是字典。最好的描述方式是显示一些代码:

    class MyClass
    {
        public int ID;
        public Dictionary<int, int> Dict = new Dictionary<int, int>();
    }

现在创建一些对象:

        List<MyClass> list = new List<MyClass>();
        MyClass mc1 = new MyClass();
        list.Add(mc1); mc1.ID = 1; mc1.Dict.Add(1, 1);

        MyClass mc2 = new MyClass();
        list.Add(mc2); mc2.ID = 1; mc2.Dict.Add(1, 1);

        MyClass mc3 = new MyClass();
        list.Add(mc3); mc3.ID = 1; mc3.Dict.Add(1, 2);

        MyClass mc4 = new MyClass();
        list.Add(mc4); mc4.ID = 2; mc4.Dict.Add(1, 1);

我想要完成的是通过 ID 和 Dict 来区分。结果应如下所示:

MyClass 对象列表(不漂亮)

1      //MyClass.ID
1,1    //MyClass.Dictionary

1
1,2

2
1,1

请注意,其中一个对象已从原始列表中删除,因为它具有重复的 ID 和 Dict(字典值)。我一直在玩其他版本的:

        var s = from p in list
                 group p by p.ID into group1
                 from group2 in
                     (from p in group1 group p by p.Dict)
                 group group2 by group1.Key;

但只是没有任何运气。感谢人们对解决此问题的任何见解。

PS - 我没有更改规则,但我相信 GROUP BY 和 SELECTFIRST 会比 DISTINCT 更干净,因为它有额外的比较器代码。对任何可以使用 GROUP BY 解决此问题的人表示赞赏。

【问题讨论】:

    标签: linq distinct


    【解决方案1】:

    对于引用类型,您应该添加equality comparer 以执行您想要的操作。添加以下类:

    public class MyClassComparer : IEqualityComparer<MyClass>
        {
            public bool Equals(MyClass left, MyClass right)
            {
                if (left == null && right == null)
                {
                    return true;
                }
                if (left == null || right == null)
                {
                    return false;
                }
    
                if (left.ID == right.ID)
                {
                    if (left.Dict == null && right.Dict == null)
                    {
                        return true;
                    }
                    if (left.Dict == null || right.Dict == null)
                    {
                        return false;
                    }
                    if (left.Dict.Count != right.Dict.Count)
                    {
                        return false;
                    }
    
                    foreach(var key in left.Dict.Keys)
                    {
                        if(!right.Dict.ContainsKey(key))
                            return false;
    
                        if (left.Dict[key] != right.Dict[key])
                         return false;
                    }
    
                    return true;
                }
                else return false;
            }
    
            public int GetHashCode(MyClass author)
            {
                return (author.ID).GetHashCode();
            }
        }
    

    并在 Distinct 覆盖中使用该比较器:

    List<MyClass> list = new List<MyClass>();
    MyClass mc1 = new MyClass();
    list.Add(mc1); mc1.ID = 1; mc1.Dict.Add(1, 1);
    
    MyClass mc2 = new MyClass();
    list.Add(mc2); mc2.ID = 1; mc2.Dict.Add(1, 1);
    
    MyClass mc3 = new MyClass();
    list.Add(mc3); mc3.ID = 1; mc3.Dict.Add(1, 2);
    
    MyClass mc4 = new MyClass();
    list.Add(mc4); mc4.ID = 2; mc4.Dict.Add(1, 1);
    
    
    var result = list.Distinct(new MyClassComparer()).ToList();
    

    你应该改进GetHashCode 方法。这将是你的家庭作业:)

    【讨论】:

      【解决方案2】:

      我可以为以下内容点赞吗? :)

      var filteredList = list.GroupBy(mc => mc.ID)
                             .SelectMany(gr => gr.Distinct(new MyClassComparer()))
                             .ToList();
      

      比较器:

      public class MyClassComparer : IEqualityComparer<MyClass>
      {
          public bool Equals(MyClass a, MyClass b)
          {
              return a.Dict.Count == b.Dict.Count && !a.Dict.Except(b.Dict).Any();
          }
      
      
          public int GetHashCode(MyClass a)
          {
              return a.ID;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2017-04-10
        • 2016-03-12
        • 2021-05-12
        • 1970-01-01
        • 2019-02-28
        相关资源
        最近更新 更多