计算两个集合的交集和差值的最佳方法是什么?

发布于 2024-12-06 16:34:23 字数 383 浏览 1 评论 0原文

我有 2 个列表 ListList,它们通过相同属性 Class1.KeyClass2.Key 进行比较 (字符串),我想编写一个函数,生成 3 个列表

  1. List 两个列表中都存在的元素
  2. List 仅在第一个列表中出现的元素
  3. List 仅在第二个列表中出现的元素

有没有快速的方法来做到这一点?

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> Elements 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?

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

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

发布评论

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

评论(1

马蹄踏│碎落叶 2024-12-13 16:34:23
var requirement1 = list1.Intersect(list2);
var requirement2 = list1.Except(list2);
var requirement3 = list2.Except(list1);

对于您的 List,这将是您所需要的。如果您是为自定义类执行此操作,并且您正在寻找引用比较以外的其他内容,那么您需要确保该类正确重写 EqualsGetHashCode。或者,您可以提供 IEqualityComparer 来重载上述方法。

编辑:

好的,现在您已经在注释中指出它不是字符串列表,而是 List。在这种情况下,覆盖 Equals/GetHashCode(如果您的密钥应始终唯一地标识这些类并且您可以访问源代码)或提供 IEqualityComparer 实现(仍然涉及 Equals/GetHashCode,如果比较对于这些类是唯一的,请使用此实现)需要或者如果您无权访问 MyObject 源)。

例如:

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

如果您使用了这样的自定义相等比较器,则对上述方法的调用将是

list1.Intersect(list2, customComparerInstance);

编辑:现在您再次移动了栏,这次问题涉及两个不同的类。为此,您可以考虑使用连接操作,一个是内部连接,另一个是外部连接。

在这种情况下,

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

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

您可以编写

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;

“要获取 list2 中的项目而不匹配 list1 中的*对象”,只需反转 except1 查询中列表/项目的顺序即可。

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.

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