Skip to content

Instantly share code, notes, and snippets.

@zhaopan
Last active December 3, 2025 14:25
Show Gist options
  • Select an option

  • Save zhaopan/11cd0c14b712bfd74a256418abcd8fbf to your computer and use it in GitHub Desktop.

Select an option

Save zhaopan/11cd0c14b712bfd74a256418abcd8fbf to your computer and use it in GitHub Desktop.
List-Union-Intersect-Except
并集:var union =arps.Union(flts).ToList();
交集:var inters = arps.Intersect(flts).ToList();
差集:var except= arps.Except(flts).ToList();
@zhaopan
Copy link
Author

zhaopan commented Dec 3, 2025

using System;
using System.Collections.Generic;
using System.Linq;

namespace LinqSetOperationsDemo
{
    /// <summary>
    /// 演示用的自定义数据实体。
    /// </summary>
    public class Product
    {
        public int Id { get; set; }
        public string? Name { get; set; }
        public string? Category { get; set; }
        
        public override string ToString()
        {
            return $"[Id: {Id}, Name: {Name}, Category: {Category}]";
        }
    }

    /// <summary>
    /// 用于基于 Product 的 Id 和 Name 进行值比较的比较器。
    /// 确保 LINQ 集合操作在自定义对象上正确执行。
    /// </summary>
    public class ProductComparer : IEqualityComparer<Product>
    {
        public bool Equals(Product? x, Product? y)
        {
            if (ReferenceEquals(x, y)) return true;
            if (x is null || y is null) return false;
            
            // 只有 Id 和 Name 属性都相等,才认为是同一个 Product
            return x.Id == y.Id && 
                   StringComparer.OrdinalIgnoreCase.Equals(x.Name, y.Name);
        }

        public int GetHashCode(Product obj)
        {
            if (obj is null) return 0;
            
            // 使用 ValueTuple 组合 Id 和 Name 的哈希码
            return (obj.Id, obj.Name?.ToUpperInvariant()).GetHashCode();
        }
    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            // 集合 A: ARPs (现有产品或期望产品)
            var arps = new List<Product>
            {
                new Product { Id = 101, Name = "Laptop", Category = "Electronics" }, // 交集
                new Product { Id = 102, Name = "Monitor", Category = "Electronics" }, // 差集
                new Product { Id = 103, Name = "Keyboard", Category = "Peripherals" }, // 交集,但大小写不同
                new Product { Id = 104, Name = "Mouse", Category = "Peripherals" }, // 差集
                new Product { Id = 105, Name = "Desk", Category = "Furniture" } // 差集
            };

            // 集合 B: FLTs (传入产品或实际产品)
            var flts = new List<Product>
            {
                new Product { Id = 101, Name = "Laptop", Category = "Electronics" }, // 交集
                new Product { Id = 103, Name = "keyboard", Category = "Peripherals" }, // 交集,但大小写不同
                new Product { Id = 201, Name = "Chair", Category = "Furniture" }, // 并集独有
                new Product { Id = 202, Name = "Webcam", Category = "Electronics" } // 并集独有
            };
            
            // 实例化自定义比较器
            var comparer = new ProductComparer();

            Console.WriteLine("--- 原始集合数据 ---");
            Console.WriteLine($"ARPs (A) 数量: {arps.Count}");
            Console.WriteLine($"FLTs (B) 数量: {flts.Count}");
            Console.WriteLine("----------------------\n");

            // 1. 并集 (Union):A 或 B 中所有不重复的元素
            // 预期结果: 101, 102, 103, 104, 105, 201, 202 (共 7 个)
            var union = arps.Union(flts, comparer).ToList();
            Console.WriteLine($"--- 1. 并集 (Union) - 数量: {union.Count} ---");
            foreach (var p in union)
            {
                Console.WriteLine(p);
            }
            Console.WriteLine("\n----------------------\n");


            // 2. 交集 (Intersect):A 和 B 中都存在的元素
            // 预期结果: 101, 103 (共 2 个)
            var inters = arps.Intersect(flts, comparer).ToList();
            Console.WriteLine($"--- 2. 交集 (Intersect) - 数量: {inters.Count} ---");
            foreach (var p in inters)
            {
                Console.WriteLine(p);
            }
            Console.WriteLine("\n----------------------\n");


            // 3. 差集 (Except):存在于 A 中,但不在 B 中的元素
            // 预期结果: 102, 104, 105 (共 3 个)
            var except = arps.Except(flts, comparer).ToList();
            Console.WriteLine($"--- 3. 差集 (Except) (A - B) - 数量: {except.Count} ---");
            foreach (var p in except)
            {
                Console.WriteLine(p);
            }
            Console.WriteLine("\n----------------------\n");
            
            // 4. 反向差集:存在于 B 中,但不在 A 中的元素
            // 预期结果: 201, 202 (共 2 个)
            var reverseExcept = flts.Except(arps, comparer).ToList();
            Console.WriteLine($"--- 4. 差集 (Except) (B - A) - 数量: {reverseExcept.Count} ---");
            foreach (var p in reverseExcept)
            {
                Console.WriteLine(p);
            }
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment