溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

LINQ、Lambda 表達式 、委托如何快速比較兩個集合及其需要新增、修改、刪除的對象

發(fā)布時間:2020-07-14 09:35:34 來源:億速云 閱讀:221 作者:Leah 欄目:編程語言

本篇文章為大家展示了LINQ、Lambda 表達式 、委托如何快速比較兩個集合及其需要新增、修改、刪除的對象,代碼簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

在工作中,經(jīng)常遇到需要對比兩個集合的場景,如:

  1. 頁面集合數(shù)據(jù)修改,需要保存到數(shù)據(jù)庫

  2. 全量同步上游數(shù)據(jù)到本系統(tǒng)數(shù)據(jù)庫

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

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

  2. 實體比較:表示兩個對象在業(yè)務(wù)是不是相等(唯一標識相等、次要屬性相等)。

代碼示例如下:

void Main()
{
    // 對比源集合
    var source = GenerateStudent(1, 10000, 1000);
    // 目標集合
    var target = GenerateStudent(5000, 10000, 1000);

    // 唯一標識比較
    Func<Student, Student, bool> keyCompartor = (s, t) => s.Id == t.Id;
    // 實體相等比較
    Func<Student, Student, bool> entityCompartor = (s, t) => s.Id == t.Id && s.Name.Equals(t.Name) && s.Age == t.Age;

    // 新增前準備
    Func<Student, Student> insertAction = (s) =>
    {
        return new Student
        {
            Id = s.Id,
            Name = s.Name,
            Age = s.Age,
            Operation = "Insert"
        };
    };

    // 更新前準備
    Func<Student, Student, Student> updateAction = (s, t) =>
    {
        t.Name = s.Name;
        t.Age = s.Age;
        t.Operation = "Update";

        return t;
    };

    // 刪除前準備
    Func<Student, Student> 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);

    // 后續(xù)業(yè)務(wù)
    // InsertStudents(insertingStudents);
    // UpdateStudents(updatingStudents);
    // DeleteStudents(deletingStudents);
}

// 集合去重
private void RemoveDuplicate<S, T>(List<S> source, List<T> target, Func<S, T, bool> entityCompartor,
    Func<S, S, bool> sourceKeyCompartor, Func<S, T, bool> 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<T> GetInsertingEntities<S, T>(List<S> source, List<T> target, Func<S, T, bool> keyComportor,
    Func<S, T> insertAction)
{
    var result = new List<T>();
    foreach (var s in source)
    {
        var t = target.FirstOrDefault(x => keyComportor(s, x));
        if (t == null)
        {
            // 目標集合中不存在,則新增
            result.Add(insertAction(s));
        }
    }

    return result;
}

// 獲取需要更新的對象集合
private List<T> GetUpdatingEntities<S, T>(List<S> source, List<T> target, Func<S, T, bool> keyComportor,
    Func<S, T, bool> entityCompartor, Func<S, T, T> updateAction)
{
    var result = new List<T>();
    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<T> GetDeletingEntities<S, T>(List<S> source, List<T> target,
    Func<S, T, bool> keyComportor, Func<T, T> deleteAction)
{
    var result = new List<T>();
    foreach (var t in target)
    {
        var s = source.FirstOrDefault(x => keyComportor(x, t));
        if (s == null)
        {
            // 源集合中存在,目標集合中需要刪除
            result.Add(deleteAction(t));
        }
    }

    return result;
}

// 隨機生成測試集合
private List<Student> GenerateStudent(int minId, int maxId, int maxNumber)
{
    var r = new Random();
    var students = new List<Student>();
    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,但實際使用中,兩者的類型可以不一樣,只要最終返回目標集合的類型就可以了。

上面是我對集合比較的一點心得,只滿足了小數(shù)據(jù)量的業(yè)務(wù)情景,并沒有在大數(shù)據(jù)量的情況下做過調(diào)優(yōu)。在這里也算是拋磚引玉,大家要是有更好的辦法,還希望不吝賜教。

上述內(nèi)容就是LINQ、Lambda 表達式 、委托如何快速比較兩個集合及其需要新增、修改、刪除的對象,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI