LINQ并从对象数组中删除重复项

时间:2015-02-08 15:17:32

标签: linq distinct

我试图使用两列来重新排列对象数组,其中第二列是Dictionary。描述这个的最好方法是显示一些代码:

    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更清洁,其额外的代码用于Comparer。对于那些可以使用GROUP BY来解决这个问题的人来说,可以轻拍一下。

2 个答案:

答案 0 :(得分:0)

对于参考类型,您应添加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方法。这将是你的功课:)

答案 1 :(得分:0)

以下是否可以半拍? :)

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

的Comparer:

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