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
List<Class1>
Elements that are present in both listsList<Class1>
Element开发者_如何学Cs that are present only in first listList<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.
精彩评论