Using Linq intersect with sub values?
I found this post Match elements between 2 collections with Linq in c# which explained how you can use Intersect to find matching elements between two lists.
Can you use this to match elements in two lists开发者_运维知识库 that are not of exactly the same, but have "sub values" that you want to match?
My example is this: I have two collections, each containing lists of XElements. The one with elements called <link>
and the other with elements called <file>
, each have attributes called "path", and it is this attribute I want to match. If the path attribute is equal, I want a match.
In the result set I would like a list of all the elements whose paths match the paths of the elements.
How can this be done?
I would suggest to use LambdaComparer which can be passed into the Intersect()
method as Equality Comparer, it allows specifying comparison logic in place by providing boolean condition instead introducing a new comparer class each time, so your code would be clear enough:
firstCollection.Intersect(
secondCollection,
new LambdaComparer<YourClass>(
(item1, item2) => item1.PropertyName == item2.PropertyName));
// Below are lists and User class which demonstrates LambdaComparer and Intersect()
public class User
{
public string Name { get; set; }
}
IList<User> list1 = new List<User>
{
new User {Name = "A"},
new User { Name = "B"}
};
List<User> list2 = new List<User>
{
new User {Name = "C"},
new User { Name = "B"}
};
var resultSet = list1.Intersect<User>(
list2,
new LambdaComparer<User>((item1, item2) => item1.Name == item2.Name));
Basically if you need to compare cusotm attributes, you still can encapsulate this logic into
Func<User, User, bool> userNameComparer = (user1, user2) =>
{
// check attributes using user1.GetType().GetCustomAttributes()
};
And then use this comparer funciton as:
var resultSet = list1.Intersect<User>(
list2,
new LambdaComparer<User>((item1, item2) => userNameComparer));
EDIT: Note ragarding particular impelemntaion referenced in this answer
There is could be a problem that by default for hash funciton is hardcoded 0
6 public LambdaComparer(Func<T, T, bool> lambdaComparer) :
7 this(lambdaComparer, o => 0)
8 {
9 }
This can lead to performance issues in some cases so I would recommend to refactor it as:
public LambdaComparer(Func<T, T, bool> lambdaComparer) :
this(lambdaComparer,
EqualityComparer<T>.Default.GetHashCode(o))
{
}
So it wil use built in GetHashCode()
implementation
精彩评论