如何使用LINQ、Lambda 表達式 、委託快速比較兩個集合,找出需要新增、修改、刪除的物件(附程式碼)

云罗郡主
發布: 2018-10-15 14:07:16
轉載
3200 人瀏覽過

本篇文章帶給大家的內容是關於如何使用LINQ、Lambda 表達式、委託快速比較兩個集合,找出需要新增、修改、刪除的物件(附程式碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

在工作中,常常遇到需要比較兩個集合的場景,如:

  1. 頁面集合資料修改,需要儲存到資料庫

  2. #全量同步上游資料到本系統資料庫

在這些場景中,需要識別出需要新增、更新、刪除的數據,由於每次應用是,需要比較的物件類型不一致,因此寫了一個相對通用的方法。在這個過程中,需要理解的有以下2個核心概念:

  1. 唯一標識比較: 如果兩個物件的唯一識別相等,則認為這兩個物件在業務上代表同一個東西(次要屬性是否相等暫不考慮)。

  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,但實際使用中,兩者的類型可以不一樣,只要最後回傳目標集合的類型就可以了。

上面是我對集合比較的一點心得,只滿足了小數據量的業務情景,並沒有在大數據量的情況下做過調優。這裡也算是拋磚引玉,大家要是有更好的辦法,還希望不吝賜教。

以上是如何使用LINQ、Lambda 表達式 、委託快速比較兩個集合,找出需要新增、修改、刪除的物件(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:cnblogs.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!