C# - 使用 foreach 比较两个对象列表以进行更改

Posted

技术标签:

【中文标题】C# - 使用 foreach 比较两个对象列表以进行更改【英文标题】:C# - Comparing two lists of objects for changes with foreach 【发布时间】:2017-10-14 03:52:21 【问题描述】:

对于我的课堂作业,我需要将旧的学生列表与新列表进行比较,并将新学生、删除的学生和更改的学生添加到单独的列表中。教师指定使用嵌套的 foreach 循环而不是 LINQ,但我的问题是一旦旧学生列表匹配新学生中的条目并移动到旧列表中的下一个学生,就会打破循环。

我的代码现在通过嵌套的 foreach 运行,将条目与旧列表中的第一个条目进行比较,结果出现没有 ID 匹配的结果,因此它将它们放入已删除的列表中并结束循环而不移动到旧列表中的下一个学生。

public static void CompareStudents(List<Student> oldList, List<Student> newList)
    
        foreach (Student o in oldList)
        
            foreach (Student n in newList)
            
                if (FindStudent(o.ID, n.ID))
                
                    if (CheckChanges(o, n))
                    
                        changed.Add(n);
                        break;
                    
                
                else
                
                    removed.Add(o);
                    break;
                
            
        
    

    private static bool FindStudent(string oldID, string newID)
    
        if (newID.Equals(oldID))
        
            return true;
        
        else
        
            return false;
        
    

    public static bool CheckChanges(Student oldStu, Student newStu)
    
        if (oldStu.FirstName.Equals(newStu.FirstName) && 
            oldStu.LastName.Equals(newStu.LastName) &&
            oldStu.StudentYear.Equals(newStu.StudentYear) &&
            oldStu.StudentRank.Equals(newStu.StudentRank))
        
            return false;
        
        else
        
            return true;
        
    

【问题讨论】:

啊,你的问题是什么?你只是想让我们为你完成你的作业吗? ***.com/questions/5636438/… 删除列表在哪里声明?您的要求不明确。 FindStudents()方法没用(可以换成简单比较o.ID == n.ID)。但算法也不是最好的。想象一下,你的左手和右手都有硬币。与其一直保留它们并相互比较,不如尝试找到相同的硬币并从未来的搜索中删除它们。剩下的 - 是不匹配的。 我投票决定将此问题作为离题结束,因为此问题要求提供一个特定作业解决方案,该解决方案放弃任何其他同样有效的解决方案(例如 LINQ)。 【参考方案1】:

如果您的 Student 类覆盖了 Equals 方法,那么您可以执行以下操作:

public static void CompareStudents(List<Student> oldList, List<Student> newList)

    List<Student> added = new List<Student>();
    List<Student> removed = new List<Student>();
    List<Student> changed = new List<Student>();

    foreach(Student n in newList)
        // the added list is a subset of the newList so we begin by cloning the newList
        added.Add(n);
    

    foreach (Student o in oldList)
    
        bool existsInNewList = false;
        // we remove every o from the added list
        added.Remove(o);

        foreach (Student n in newList)
        
            if (o.ID.Equals(n.ID))
            
                // o and n have the same Id
                existsInNewList = true;
                if (!o.Equals(n))
                
                    // o and n have the same Id but are different
                    changed.Add(n);
                    added.Remove(n);
                
                // eventually add a break; here so you don't loop after you've found a n that matches o
            
        
        if(!existsInNewList)
            // none of the newStudents have the same Id as o
            removed.Add(o);
        
    

最后,您应该将所有三个列表 addedremovedchanged 填入正确的 Students

【讨论】:

谢谢,这行得通。我只需要实现 CheckChanges 方法。我的导师向我们提供了嵌套 foreach 作为开始的建议,所以我陷入了这种思维方式。【参考方案2】:

使用旗帜怎么样?

        foreach (Student o in oldList)
        
            bool flag = false;
            foreach (Student n in newList)
            
                if (FindStudent(o.ID, n.ID))
                
                    if (CheckChanges(o, n))
                    
                        changed.Add(n);
                        flag = true;
                        break;
                    
                
                else
                
                    removed.Add(o);
                    flag = true;
                    break;
                
            
            if(flag) continue;
        

【讨论】:

【参考方案3】:

我认为你应该使用如下代码:

List<Student> OldStudents = new List<Student>();
List<Student> NewStudents = new List<Student>();
List<Student> StudentsEdit = new List<Student>();

 foreach (var oStud in OldStudents)
     
        foreach (var nStud in NewStudents)
        
          if (oStud != nStud)
            StudentsEdit.Add(oStud);
        
     

Instructor 建议我解释 LINQ,我的错, 希望这会有所帮助。

问候,

N 鲍阿

【讨论】:

...讲师指定使用嵌套的 foreach 循环而不是 LINQ... 这在添加、删除和更改的项目之间没有区别,您甚至在从旧学生列表中获取结果值时错过添加的学生(OP 也是如此) 哇!您的编辑更糟糕,因为您的 StudentsEdit 列表将包含太多学生(想想旧列表中的每个学生,新列表中的几乎每个学生都与它不同,因此您将其添加到您的编辑列表中) 您的示例将 每个 oStud 对象添加到结果列表 几次 次。对于每个存在且不同的nStud(最常见的是NewStudents.Length - 1),有几个=。错误的输出,编辑、添加和删除之间没有区别,加上错误的相等比较。此代码不是所提问题的答案。

以上是关于C# - 使用 foreach 比较两个对象列表以进行更改的主要内容,如果未能解决你的问题,请参考以下文章

如何获取 linq `ForEach` 语句以返回有关为每个列表对象进行的方法调用的数据?

C#检查foreach为null判断

c# foreach(对象中的属性)...有没有一种简单的方法可以做到这一点?

C# 使用IEnumerable,yield 返回结果,同时使用foreach时,在循环内修改变量的值无效

使用.forEach和.some比较两个Observable,如数组

C#中foreach用法