1

我发现这篇文章Match elements between 2 collections with Linq in c#解释了如何使用 Intersect 查找两个列表之间的匹配元素。

您可以使用它来匹配两个列表中不完全相同但具有您想要匹配的“子值”的元素吗?

我的示例是这样的:我有两个集合,每个集合都包含 XElement 列表。一个带有称为元素<link>的元素,另一个带有称为元素的元素<file>,每个都有称为“路径”的属性,而我要匹配的正是这个属性。如果路径属性相等,我想要一个匹配。

在结果集中,我想要一个路径与元素路径匹配的所有元素的列表。

如何才能做到这一点?

4

1 回答 1

2

我建议使用LambdaComparer,它可以作为 Equality Comparer 传递到Intersect()方法中,它允许通过提供布尔条件而不是每次引入新的比较器类来指定比较逻辑,因此您的代码将足够清晰:

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

基本上如果你需要比较 cusotm 属性,你仍然可以把这个逻辑封装成

Func<User, User, bool> userNameComparer = (user1, user2) =>
{
 // check attributes using user1.GetType().GetCustomAttributes()
};

然后将此比较器功能用作:

   var resultSet = list1.Intersect<User>(
                     list2, 
                     new LambdaComparer<User>((item1, item2) => userNameComparer));

编辑:注意这个答案中引用的特定 impelemntaion 可能存在一个问题,默认情况下哈希函数是硬编码的0

6  public LambdaComparer(Func<T, T, bool> lambdaComparer) :
7                this(lambdaComparer, o => 0)
8            {
9            }

在某些情况下,这可能会导致性能问题,因此我建议将其重构为:

public LambdaComparer(Func<T, T, bool> lambdaComparer) :
                this(lambdaComparer, 
                      EqualityComparer<T>.Default.GetHashCode(o))
            {
            }

所以它将使用内置的GetHashCode()实现

于 2011-08-13T10:17:40.243 回答