如何使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象(附代码)

本篇文章给大家带来的内容是关于如何使用linq、lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

在工作中,经常遇到需要对比两个集合的场景,如:

页面集合数据修改,需要保存到数据库

全量同步上游数据到本系统数据库

在这些场景中,需要识别出需要新增、更新、删除的数据,由于每次应用是,需要比较的对象类型不一致,因此写了个相对通用的方法。这个过程中,需要理解的有以下2个核心概念:

唯一标识比较: 如果两个对象的唯一标识相等,则认为这两个对象在业务上代表同一个东西(次要属性是否相等暂不考虑)。

实体比较:表示两个对象在业务是不是相等(唯一标识相等、次要属性相等)。

代码示例如下:

void Main(){    // 对比源集合    var source = GenerateStudent(1, 10000, 1000);    // 目标集合    var target = GenerateStudent(5000, 10000, 1000);    // 唯一标识比较    Func keyCompartor = (s, t) => s.Id == t.Id;    // 实体相等比较    Func entityCompartor = (s, t) => s.Id == t.Id && s.Name.Equals(t.Name) && s.Age == t.Age;    // 新增前准备    Func insertAction = (s) =>    {        return new Student        {            Id = s.Id,            Name = s.Name,            Age = s.Age,            Operation = "Insert"        };    };    // 更新前准备    Func updateAction = (s, t) =>    {        t.Name = s.Name;        t.Age = s.Age;        t.Operation = "Update";        return t;    };    // 删除前准备    Func deleteAction = (t) =>    {        t.Operation = "Delete";        return t;    };    // 去掉相等对象    RemoveDuplicate(source, target, entityCompartor, (s1, s2) => s1.Id == s2.Id, keyCompartor);    // 需要新增的集合    var insertingStudents = GetInsertingEntities(source, target, keyCompartor, insertAction);    // 需要更新的集合    var updatingStudents = GetUpdatingEntities(source, target, keyCompartor, entityCompartor, updateAction);    // 需要删除的集合    var deletingStudents = GetDeletingEntities(source, target, keyCompartor, deleteAction);    // 后续业务    // InsertStudents(insertingStudents);    // UpdateStudents(updatingStudents);    // DeleteStudents(deletingStudents);}// 集合去重private void RemoveDuplicate(List source, List target, Func entityCompartor,    Func sourceKeyCompartor, Func keyComportor){    var sameEntities = source.Where(s => target.Exists(t => entityCompartor(s, t))).ToList();    source.RemoveAll(s => sameEntities.Exists(s2 => sourceKeyCompartor(s, s2)));    target.RemoveAll(t => sameEntities.Exists(s => keyComportor(s, t)));}// 获取需要新增的对象集合private List GetInsertingEntities(List source, List target, Func keyComportor,    Func insertAction){    var result = new List();    foreach (var s in source)    {        var t = target.FirstOrDefault(x => keyComportor(s, x));        if (t == null)        {            // 目标集合中不存在,则新增            result.Add(insertAction(s));        }    }    return result;}// 获取需要更新的对象集合private List GetUpdatingEntities(List source, List target, Func keyComportor,    Func entityCompartor, Func updateAction){    var result = new List();    foreach (var s in source)    {        var t = target.FirstOrDefault(x => keyComportor(s, x));        if (t != null && !entityCompartor(s, t))        {            // 目标集合中存在,但是次要属性不相等,则更新            result.Add(updateAction(s, t));        }    }    return result;}// 获取需要删除的对象集合private List GetDeletingEntities(List source, List target,    Func keyComportor, Func deleteAction){    var result = new List();    foreach (var t in target)    {        var s = source.FirstOrDefault(x => keyComportor(x, t));        if (s == null)        {            // 源集合中存在,目标集合中需要删除            result.Add(deleteAction(t));        }    }    return result;}// 随机生成测试集合private List GenerateStudent(int minId, int maxId, int maxNumber){    var r = new Random();    var students = new List();    for (int i = 0; i  s.Id).Select(s => s.First()).ToList();}public class Student{    public int Id { get; set; }    public string Name { get; set; }    public int Age { get; set; }    public string Operation { get; set; }}

例子中源集合与目标集合使用了相同的对象Student,但实际使用中,两者的类型可以不一样,只要最终返回目标集合的类型就可以了。

上面是我对集合比较的一点心得,只满足了小数据量的业务情景,并没有在大数据量的情况下做过调优。在这里也算是抛砖引玉,大家要是有更好的办法,还希望不吝赐教。

以上就是如何使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象(附代码)的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1432878.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月17日 08:42:02
下一篇 2025年12月17日 08:42:07

相关推荐

  • nodejs的npm常用命令集合

    这次给大家带来nodejs的npm常用命令集合,使用nodejs的npm常用命令集合注意事项有哪些,下面就是实战案例,一起来看一下。 NPM提供了很多命令,例如install和publish,使用npm help可查看所有命令。 使用npm help 可查看某条命令的详细帮助,例如npm help …

    好文分享 2025年12月21日
    000
  • 怎样使用Node.js操作集合?

    答案:Node.js通过数据库驱动实现集合的增删改查,需选择合适数据库及驱动,使用异步方式处理操作与错误,并通过索引、批量操作、投影、分页、连接池等手段优化性能。 Node.js操作集合,本质上就是利用Node.js的强大能力与数据库进行交互,实现对数据的增删改查等操作。关键在于选择合适的数据库驱动…

    2025年12月20日
    000
  • C++的Lambda和std::function的开销_C++中不同可调用对象的性能分析

    Lambda表达式因编译期类型确定且可内联,性能最优;std::function因类型擦除和间接调用引入运行时开销,适合需统一接口的场景但性能较低。 在C++中,函数调用的性能不仅取决于算法本身,还受到可调用对象类型的影响。Lambda表达式、函数指针、std::function 等都可以作为回调使…

    2025年12月19日
    000
  • C++ set用法详解_C++集合插入与查找操作

    C++中的set是基于红黑树实现的关联容器,自动保持元素唯一且有序。支持O(log n)时间复杂度的插入、删除和查找操作。需包含头文件,定义如std::set s;,可自定义排序规则如std::set descSet;。使用insert()添加元素,返回pair指示是否插入成功;find()返回指向…

    2025年12月19日
    000
  • C++中的lambda捕获列表是什么_C++匿名函数与lambda捕获技巧

    Lambda捕获列表位于方括号中,用于指定lambda访问外部变量的方式。例如[x]按值捕获,[&x]按引用捕获,[=]按值捕获所有,[&]按引用捕获所有,支持混合捕获和this捕获;C++14起支持初始化捕获如[y=x+1];需注意引用捕获的悬空风险与生命周期管理,合理使用可提升代…

    2025年12月19日
    000
  • c++怎么用lambda捕获this指针_c++ lambda表达式捕获this方法详解

    在C++中,lambda通过捕获this指针访问类成员,[this]可直接捕获当前对象,使lambda能访问非静态成员变量和函数,如[ this ](){ std::cout 在C++中,lambda表达式可以捕获当前对象的this指针,以便在lambda内部访问类的成员变量和成员函数。这是因为在类…

    2025年12月19日
    000
  • c++怎么使用lambda作为函数参数_c++将lambda作为参数的用法

    Lambda表达式可作为参数传递给函数,常用模板或std::function接收。1. 使用函数模板可高效接受Lambda,编译器能内联调用,适用于泛型算法;2. std::function提供统一接口,便于多Lambda切换,但有运行时开销;3. 带参数和返回值的Lambda可通过匹配函数签名传递…

    2025年12月19日
    000
  • c++中如何使用lambda排序vector_c++ lambda排序vector实现

    使用lambda表达式可灵活自定义std::sort排序规则,支持基本类型升序、结构体多条件排序及捕获外部变量实现动态排序,提升代码简洁性与可读性。 在C++中,可以使用lambda表达式作为排序的比较函数,结合std::sort对std::vector进行灵活排序。这种方式简洁、直观,特别适合自定…

    2025年12月19日
    000
  • C++ 函数的类方法如何使用 lambda 表达式?

    使用 lambda 表达式可以为 c++++ 类方法赋值,该过程包括创建 lambda 表达式、将其赋值给方法指针和最后使用赋值的 lambda 表达式。实战案例包括动态回调,其中 lambda 表达式用于创建回调函数,这些回调函数在运行时确定。 使用 Lambda 表达式为 C++ 中的类方法赋值…

    2025年12月18日
    000
  • C++ 函数指针如何用于Lambda表达式?

    使用函数指针用于 lambda 表达式,使我们可以创建指向特定 lambda 表达式的指针,用于将 lambda 表达式作为参数传递给函数:定义函数指针类型,指向接受所需参数和返回值类型的函数。创建一个 lambda 表达式,并将其分配给函数指针。调用函数指针,执行 lambda 表达式。 C++ …

    2025年12月18日
    000
  • Lambda 表达式如何与智能指针结合使用?

    将 lambda 表达式与智能指针结合使用可提高代码的可读性和可维护性。lambda 表达式是一种匿名函数,它可以通过捕获列表访问智能指针管理的对象。智能指针是一类自动释放对象的指针,可防止内存泄漏和悬垂指针,常用的类型包括 std::unique_ptr、std::shared_ptr 和 std…

    2025年12月18日
    000
  • C++ Lambda 表达式在实际项目中的应用示例有哪些?

    c++++ lambda 表达式应用示例:事件处理:处理事件触发时的特定动作,例如 gui 中的按钮点击事件。数据处理:对数据集合进行操作,例如对容器中的元素进行排序。函数对象替代:作为函数对象的替代,允许在运行时动态创建函数。算法优化:重写业务逻辑的比较函数,以优化算法。匿名线程和回调:创建匿名线…

    2025年12月18日
    000
  • C++ Lambda 表达式如何实现延迟求值?

    C++ Lambda 表达式如何实现延迟求值? 延迟求值,又称惰性求值,是指仅在需要结果时才对其进行计算。这可以在某些情况下提高效率,例如当计算代价很大且不会立即使用结果时。 C++ 中 Lambda 表达式支持延迟求值,通过将 Lambda 表达式捕获为 [=] 来实现,其中 ‘=&#…

    2025年12月18日
    000
  • C++ Lambda 表达式的性能考虑有哪些?

    使用 lambda 表达式时需要注意性能影响:1. 编译时间延长;2. 代码体积增大;3. 执行速度低于常规函数,原因在于需要捕获和传递闭包变量。建议仅在需要时使用 lambda 表达式,并考虑使用 std::function 或 std::bind 来优化性能。 C++ Lambda 表达式的性能…

    2025年12月18日
    100
  • C++ Lambda 表达式和函数指针有什么关系?

    lambda 表达式和函数指针在 c++++ 中都是捕获和传递函数的机制,它们之间存在密切关系。lambda 表达式可以转换为函数指针,反之亦然,这种转换是自动的。lambda 表达式是匿名函数对象,而函数指针指向函数地址。在实战中,两者都可以用于定义比较函数或其他内联函数,例如上面比较两个整数的案…

    2025年12月18日
    000
  • Lambda 表达式的类型推导规则是什么?

    lambda 表达式的类型推导规则:参数类型:从函数接口的抽象方法中推导。返回值类型:从函数接口的抽象方法中推导。推导示例:实现函数接口 myinterface 并使用 “(x, y) -> x + y”,则 lambda 表达式的类型为 “(int x, …

    2025年12月18日
    000
  • Lambda 表达式在并行编程中如何应用?

    Lambda 表达式在并行编程中的应用 Lambda 表达式是一种匿名函数,可以让开发人员以简洁的方式编写代码。在并行编程中,它们特别有用,因为它允许开发人员轻松地将代码分解为可并行执行的小块。 Java 中的 Lambda 表达式 Java 中的 Lambda 表达式具有以下语法: (parame…

    2025年12月18日
    000
  • 如何使用 C++ Lambda 表达式捕获变量

    lambda 表达式允许在 c++++ 中通过捕获机制访问定义范围之外的变量。有三种捕获类型:值(只读副本)、引用(引用变量)和指针(指针变量)。捕获变量的语法为:[&] 捕获所有变量的引用,[=] 捕获所有变量的值,[变量名] 捕获指定变量的值或引用。使用 lambda 表达式捕获变量时,…

    2025年12月18日
    000
  • C++ Lambda 表达式中可以嵌套其他 Lambda 表达式吗?

    c++++ lambda 表达式支持嵌套,允许创建嵌套的 lambda 表达式。这可用于构建更复杂和可读的代码。嵌套的 lambda 可以访问外层 lambda 的捕获变量,但反之则不行。然而,需要注意闭包和内存泄漏的问题,并避免过度复杂性。 C++ Lambda 表达式中的 Lambda 嵌套 C…

    2025年12月18日
    000
  • 用 Lambda 表达式简化 C++ 中的匿名函数声明

    使用 Lambda 表达式简化 C++ 中的匿名函数声明 在 C++ 中,匿名函数是一个没有名称的函数对象。通常用于需要临时函数或回调函数的情况。传统的匿名函数声明语法如下: struct 匿名函数 { // 函数体}; 这种语法虽然有效,但较为冗长。Lambda 表达式提供了一种简化的方式来声明匿…

    2025年12月18日
    000

发表回复

登录后才能评论
关注微信