开发者

What is the best way to compute intersection and difference of 2 sets?

开发者 https://www.devze.com 2023-04-08 11:33 出处:网络
I have 2 lists List<Class1> and List<Class2> that are compared by same property Class1.Key and Class2.Key (string) and I want to write a function that will produce 3 lists out of them

I have 2 lists List<Class1> and List<Class2> that are compared by same property Class1.Key and Class2.Key (string) and I want to write a function that will produce 3 lists out of them

  1. List<Class1> Elements that are present in both lists
  2. List<Class1> Element开发者_如何学Cs that are present only in first list
  3. List<Class2> Elements that are present only in second list

Is there a quick way to do that?


var requirement1 = list1.Intersect(list2);
var requirement2 = list1.Except(list2);
var requirement3 = list2.Except(list1);

For your List<string>, this will be all you need. If you were doing this for a custom class and you were looking for something other than reference comparisons, you'd want to ensure that the class properly overrided Equals and GetHashCode. Alternatively, you could provide an IEqualityComparer<YourType> to overloads of the above methods.

Edit:

OK, now you've indicated in the comments that it isn't a list of string, it's a List<MyObject>. In which case, override Equals/GetHashCode (if your key should uniquely identify these classes all the time and you have access to the source code) or provide an IEqualityComparer implementation (still involves Equals/GetHashCode, use this if the comparison is unique to these requires or if you do not have access to MyObject source).

For example:

class MyObjectComparer : IEqualityComparer<MyObject>
{
     public bool Equals(MyObject x, MyObject y)
     {
          // implement appropriate comparison of x and y, check for nulls, etc 
     }

     public int GetHashCode(MyObject obj)
     {
          // validate if necessary
          return obj.KeyProperty.GetHashCode();
     }
}

If you used a custom equality comparer such as this, the call to the above methods would be

list1.Intersect(list2, customComparerInstance);

Edit: And now you've moved the bar yet again, this time the problem deals with two distinct classes. For this, you would consider utilizing join operations, one being an inner, the other being an outer.

In the case of

class Class1
{
    public string Foo { get; set; } 
}

class Class2
{
    public string Bar { get; set; }
}

You could write

var intersect = from item1 in list1
                join item2 in list2
                on item1.Foo equals item2.Bar
                select item1;

var except1 = from item1 in list1
                join item2 in list2
                on item1.Foo equals item2.Bar into gj
                from item2 in gj.DefaultIfEmpty()
                where item2 == null
                select item1;

To get the items in list2 without matching* objects in list1, simply reverse the order of the lists/items in the except1 query.

0

精彩评论

暂无评论...
验证码 换一张
取 消