当前位置: 首页 > news >正文

lamda 对比两个list_如何使用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 < 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,但实际使用中,两者的类型可以不一样,只要最终返回目标集合的类型就可以了。

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

相关文章:

  • 论《Java替代C语言的可能性》
  • vue添加定位功能_Vue项目引用百度地图并实现搜索定位等功能
  • 通讯中的字节网络顺序和字节主机顺序
  • python tableau自动化导出_使用 Python 导出 Tableau 自定义形状 (Extracting Tableau Custom Shapes Using Python)...
  • tableau三轴该怎么做_在视图中为多个度量添加轴
  • 投资者的七个等级
  • python正则表达读取word_python 正则表达
  • python中土耳其编码范围_Python-编码这趟浑水
  • 做聪明的人很容易,但做善良的人很难
  • webis个人主页设计_个人网页(个人主页)设计论文
  • [个人] 确立了新的研究方向
  • java读书心得_范文精选-读书心得体会-java夜未眠读书心得
  • 经典导航菜单脚本收藏
  • axure 导入元件库显示不出白框_如何用Axure画出Web后台产品的面包屑组件
  • Oracle常用命令
  • HTTP 简介
  • Javascript基础之Array数组API
  • leetcode378. Kth Smallest Element in a Sorted Matrix
  • Shadow DOM 内部构造及如何构建独立组件
  • Spark in action on Kubernetes - Playground搭建与架构浅析
  • SpringBoot 实战 (三) | 配置文件详解
  • Unix命令
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 探索 JS 中的模块化
  • 微信小程序:实现悬浮返回和分享按钮
  • 我从编程教室毕业
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • 阿里云ACE认证学习知识点梳理
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • #数学建模# 线性规划问题的Matlab求解
  • (145)光线追踪距离场柔和阴影
  • (C语言)字符分类函数
  • (ros//EnvironmentVariables)ros环境变量
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (三)模仿学习-Action数据的模仿
  • (转)ObjectiveC 深浅拷贝学习
  • (最完美)小米手机6X的Usb调试模式在哪里打开的流程
  • .NET建议使用的大小写命名原则
  • .NET业务框架的构建
  • @RequestBody详解:用于获取请求体中的Json格式参数
  • [383] 赎金信 js
  • [C#]winform使用引导APSF和梯度自适应卷积增强夜间雾图像的可见性算法实现夜间雾霾图像的可见度增强
  • [C++]拼图游戏
  • [Codeforces] combinatorics (R1600) Part.2
  • [Design Pattern] 工厂方法模式
  • [element-ui] el-dialog 中的内容没有预先加载,因此无法获得内部元素的ref 的解决方案
  • [ERROR]-Error: failure: repodata/filelists.xml.gz from addons: [Errno 256] No more mirrors to try.
  • [Flutter]WindowsPlatform上运行遇到的问题总结
  • [hdu 2826] The troubles of lmy [简单计算几何 - 相似]
  • [HOW TO]如何在iPhone应用程序中发送邮件
  • [Java] 图说 注解