簡體   English   中英

在 C# 中使用 linq 比較兩個列表

[英]Compare two list using linq in C#

我們有下面的學生列表,我想通過比較學生姓名來比較兩個列表(來源、目的地)。 如果學生姓名發生變化,那么我們需要執行更新查詢,以更新新的學生姓名。

Public Class Student
{
   public int StudentId { get; set; }
   public int StudentName { get; set; }
}

我們需要將學生名單與來源和目的地進行比較。

IList<Student> studentList1 = new List<Student>() { 
        new Student() { StudentId = 1, StudentName = "John", Age = 18 } ,
        new Student() { StudentId = 2, StudentName = "Steve",  Age = 15 }

};

IList<Student> studentList2 = new List<Student>() { 
        new Student() { StudentId = 1, StudentName = "Michaiel", Age = 18 } ,
        new Student() { StudentId = 2, StudentName = "Mike",  Age = 15 } ,
};

所以,到目前為止,我們正在考慮使用SequenceEqual方法來比較兩個列表。 那么,這種方法是否也比較區分大小寫的值和任何其他更好的替代方法?

這種方法可以用於其他數據類型,如 boolean、int 等。

對此的任何幫助表示贊賞!

像大多數 LINQ 方法一樣, SequenceEquals接受一個comparer參數,該參數允許您使用不同的比較來比較元素。

您可以直接實現 IEqualityComparer 接口或從EqualityComparer繼承:

class StudentNameComparer: EqualityComparer<Student>
{
    public override bool Equals(Student st1, Student st2)
    {
        return String.Equals(st1?.StudentName,st2?.StudentName);
    }

    public override int GetHashCode(Student st)
    {
        return st.Name.GetHashCode();
    }
}

這允許您檢查差異:

var hasDiffs=studentList1.SequenceEquals(studentList2, new StudentNameComparer());

除了有一個比較器。 您可以通過以下方式找到實際差異:

var diffs=studentList1.Except(studentList2,new StudentNameComparer());

.NET 中的字符串比較區分大小寫。 如果您想使用不區分大小寫的比較,您可能應該提取並比較名稱。 您可以將String.Equals與所需的StringComparison參數一起使用,例如: String.Equals(st1.StudentName,st2.StudentName,StringComparison.OrdinalIgnoreCase)但是 hash 代碼呢?

StringComparer已經實現了適當的比較和 hash 代碼,因此更易於使用:

var studentNames1=studentList1.Select(st=>st.StudentName);
var studentNames2=studentList2.Select(st=>st.StudentName);
var haveDiffs=studentNames1.SequenceEqual(studentName2,StringComparer.OrdinalIgnoreCase);

如果學生姓名發生變化,那么我們需要執行更新查詢,以更新新的學生姓名。

根據該陳述,您需要了解的不僅僅是兩個列表是否包含相同的成員。 在我看來,您應該遍歷第一個列表並查看第二個列表中是否有更新的名稱:

foreach (var student in studentList1)
{
    var otherStudent = studentList2.FirstOrDefault(other => 
        other.SudentId == student.StudentId && 
        !other.StudentName.Equals(student.StudentName, StringComparison.OrdinalIgnoreCase));

    if (otherStudent != null)
    {
        // Update student record with student.StudentId to otherStudent.StudentName
    }
}

同樣,您可以使用以下內容獲取所有具有新名稱的學生:

var studentsWithNewNames = studentList2.Where(s2 =>
    studentList1.Any(s1 =>
        s1.StudentId == s2.StudentId &&
        !s1.StudentName.Equals(s2.StudentName, StringComparison.OrdinalIgnoreCase)));

foreach (var newNameStudent in studentsWithNewNames)
{
    // Update student with newNameStudent.StudentId to newNameStudent.StudentName
}

或者你可以 go 完全 linq ,然后做:

studentList2.Where(s2 => studentList1.Any(s1 =>
    s1.StudentId == s2.StudentId &&
    !s1.StudentName.Equals(s2.StudentName, StringComparison.OrdinalIgnoreCase)))
    .ToList()
    .ForEach(student =>
    {
        // update student.StudentId with student.StudentName
    });

另請注意,您不應將Age作為屬性存儲,因為它在不斷變化。 您應該存儲DateOfBirth ,然后將Age顯示為計算字段。 並且Name應該是一個string (另請注意,您不需要在屬性名稱中重復 class 名稱):

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    public TimeSpan Age => DateTime.Now - DateOfBirth;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM