Heim  >  Artikel  >  Backend-Entwicklung  >  So verwenden Sie LINQ, Lambda-Ausdrücke und Delegaten, um schnell zwei Sammlungen zu vergleichen und Objekte zu finden, die hinzugefügt, geändert oder gelöscht werden müssen (Code im Anhang)

So verwenden Sie LINQ, Lambda-Ausdrücke und Delegaten, um schnell zwei Sammlungen zu vergleichen und Objekte zu finden, die hinzugefügt, geändert oder gelöscht werden müssen (Code im Anhang)

云罗郡主
云罗郡主nach vorne
2018-10-15 14:06:193264Durchsuche

Der Inhalt dieses Artikels befasst sich mit der Verwendung von LINQ, Lambda-Ausdrücken und Delegaten, um schnell zwei Sammlungen zu vergleichen und die Objekte herauszufinden, die hinzugefügt, geändert und gelöscht werden müssen (mit Code), was einen bestimmten Referenzwert hat . Freunde in Not können darauf verweisen, ich hoffe, es wird Ihnen hilfreich sein.

Bei der Arbeit stoßen wir oft auf Szenarien, in denen wir zwei Sammlungen vergleichen müssen, wie zum Beispiel:

  1. Änderungen der Seitensammlungsdaten müssen in der Datenbank gespeichert werden

  2. Alle Upstream-Daten mit der Systemdatenbank synchronisieren

In diesen Szenarien ist es notwendig, die Daten zu identifizieren, die hinzugefügt, aktualisiert und gelöscht werden müssen Da bei jeder Anwendung die zu vergleichenden Objekttypen inkonsistent sind, habe ich eine relativ allgemeine Methode geschrieben. In diesem Prozess müssen Sie die folgenden zwei Kernkonzepte verstehen:

  1. Eindeutiger ID-Vergleich: Wenn die eindeutigen IDs zweier Objekte gleich sind, sind die beiden Objekte gleich Die Objekte werden betriebswirtschaftlich als gleich angesehen (ob die sekundären Attribute gleich sind, wird noch nicht berücksichtigt).

  2. Entitätsvergleich : Gibt an, ob zwei Objekte im Geschäftsleben gleich sind (eindeutige Bezeichner sind gleich, sekundäre Attribute sind gleich).

Das Codebeispiel lautet wie folgt:

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);

    // 后续业务
    // 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; }
}

Im Beispiel verwenden die Quellsammlung und die Zielsammlung dasselbe ObjektStudent, aber bei der tatsächlichen Verwendung Die beiden Typen können unterschiedlich sein, solange der Typ der Zielsammlung letztendlich zurückgegeben wird.

Das Obige ist meine Erfahrung zum Sammlungsvergleich. Es entspricht nur dem Geschäftsszenario eines kleinen Datenvolumens und wurde nicht auf ein großes Datenvolumen abgestimmt. Dies kann als Ausgangspunkt betrachtet werden. Wenn jemand einen besseren Weg hat, hoffe ich, dass Sie mir einen Rat geben können.

Das obige ist der detaillierte Inhalt vonSo verwenden Sie LINQ, Lambda-Ausdrücke und Delegaten, um schnell zwei Sammlungen zu vergleichen und Objekte zu finden, die hinzugefügt, geändert oder gelöscht werden müssen (Code im Anhang). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:cnblogs.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen