使用 Linq 与子值相交?

发布于 2024-11-29 04:18:30 字数 486 浏览 5 评论 0原文

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

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

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

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

这怎么能做到呢?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

dawn曙光 2024-12-06 04:18:30

我建议使用 LambdaComparer ,它可以传递到Intersect() 方法作为 Equality Comparer,它允许通过提供布尔条件来指定比较逻辑相反,每次都引入一个新的比较器类,这样您的代码就会足够清晰:

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

基本上,如果您需要比较自定义属性,您仍然可以将此逻辑封装到

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

编辑:注意特定的实现此答案中引用
可能存在一个问题,默认情况下哈希函数是硬编码 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 () 实现

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文