0

0

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

云罗郡主

云罗郡主

发布时间:2018-10-15 14:06:19

|

3575人浏览过

|

来源于cnblogs

转载

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

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

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

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

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

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

    宣小二
    宣小二

    宣小二:媒体发稿平台,自媒体发稿平台,短视频矩阵发布平台,基于AI驱动的企业自助式投放平台。

    下载
  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 < maxNumber; i++)
    {
        students.Add(new Student
        {
            Id = r.Next(minId, maxId),
            Name = $"name: {r.Next(1, 10)}",
            Age = r.Next(6, 10)
        });
    }

    return students.GroupBy(s => 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,但实际使用中,两者的类型可以不一样,只要最终返回目标集合的类型就可以了。

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

相关专题

更多
lambda表达式
lambda表达式

Lambda表达式是一种匿名函数的简洁表示方式,它可以在需要函数作为参数的地方使用,并提供了一种更简洁、更灵活的编码方式,其语法为“lambda 参数列表: 表达式”,参数列表是函数的参数,可以包含一个或多个参数,用逗号分隔,表达式是函数的执行体,用于定义函数的具体操作。本专题为大家提供lambda表达式相关的文章、下载、课程内容,供大家免费下载体验。

204

2023.09.15

python lambda函数
python lambda函数

本专题整合了python lambda函数用法详解,阅读专题下面的文章了解更多详细内容。

190

2025.11.08

Python lambda详解
Python lambda详解

本专题整合了Python lambda函数相关教程,阅读下面的文章了解更多详细内容。

49

2026.01.05

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

352

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2075

2023.08.14

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

347

2023.08.31

MySQL恢复数据库
MySQL恢复数据库

MySQL恢复数据库的方法有使用物理备份恢复、使用逻辑备份恢复、使用二进制日志恢复和使用数据库复制进行恢复等。本专题为大家提供MySQL数据库相关的文章、下载、课程内容,供大家免费下载体验。

255

2023.09.05

vb中怎么连接access数据库
vb中怎么连接access数据库

vb中连接access数据库的步骤包括引用必要的命名空间、创建连接字符串、创建连接对象、打开连接、执行SQL语句和关闭连接。本专题为大家提供连接access数据库相关的文章、下载、课程内容,供大家免费下载体验。

323

2023.10.09

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

19

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
极客学院Java8新特性视频教程
极客学院Java8新特性视频教程

共17课时 | 3.8万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.3万人学习

Pandas 教程
Pandas 教程

共15课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号