如何提取两个列表中的差异?

3

如下所示,我需要一个输出来显示添加更改删除的学生。虽然我已经研究了如何精确地做到这一点,并在RemovedStudents()中发现了我目前设置的内容。有没有什么例子可以帮助我完成添加、更改和删除学生方法?我会非常感激任何帮助!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace OldandNewStudents
{
    class Program
    {
        static void Main(string[] args)
        {
            //Display lists of students
            Console.WriteLine("Here is the list of old students: ");
            ShowStudents(GetStudentsOld());
            Console.WriteLine("Here is the list of new students: ");
            ShowStudents(GetStudentsNew());

            //Show the additions
            Console.WriteLine("Here is the list Additions: ");

            //Show the changes
            Console.WriteLine("Here is the list of Changes: ");

            //Show the removed students
            Console.WriteLine("Here is the list of removed students: ");
            RemovedStudents(GetStudentsNew(), GetStudentsOld());
            Console.ReadLine();
        }

        public static List<Student> GetStudentsOld()
        {
            List<Student> students = new List<Student>();

            students.Add(new Student("111", "Michael", "Tucker", "Junior", 10));
            students.Add(new Student("222", "Svetlana", "Omelchenko", "Senior", 2));
            students.Add(new Student("333", "Michiko", "Osada", "Senior", 7));
            students.Add(new Student("444", "Hugo", "Garcia", "Junior", 16));
            students.Add(new Student("555", "Cesar", "Garcia", "Freshman", 4));
            students.Add(new Student("666", "Fadi", "Fakhouri", "Senior", 72));
            students.Add(new Student("777", "Hanying", "Feng", "Senior", 11));
            students.Add(new Student("888", "Debra", "Garcia", "Junior", 41));
            students.Add(new Student("999", "Terry", "Adams", "Senior", 6));
            students.Add(new Student("211", "Bob", "Stephenson", "Junior", 150));
            return students;
        }

        public static List<Student> GetStudentsNew()
        {
           List<Student> students = new List<Student>();

            students.Add(new Student("111", "Michael", "Tucker", "Junior", 10));
            students.Add(new Student("222", "Svetlana", "Omelchenko", "Senior", 2));
            students.Add(new Student("333", "Michiko", "Osada", "Senior", 7));
            students.Add(new Student("311", "Sven", "Mortensen", "Freshman", 53));
            students.Add(new Student("444", "Hugo", "Garcia", "Freshman", 16));
            students.Add(new Student("555", "Cesar", "Garcia", "Freshman", 4));
            students.Add(new Student("666", "Fadi", "Fakhouri", "Senior", 72));
            students.Add(new Student("777", "Hanying", "Feng", "Senior", 11));
            students.Add(new Student("888", "Debra", "Garcia", "Junior", 41));
            students.Add(new Student("411", "Lance", "Tucker", "Junior", 60));
            students.Add(new Student("999", "Terry", "Adams", "Senior", 6));
            return students;
        }

        public static void ShowStudents(List<Student> stuList)
        {
            Console.WriteLine();

            foreach (Student s in stuList)
            {
                Console.WriteLine(s);
            }
            Console.WriteLine();
        }

        public static void RemovedStudents(List<Student> stuNewList, List<Student> stuOldList)
        {
            List<Student> removedStudents = stuNewList.Except(stuOldList).ToList();
            IEnumerable<Student> differenceQuery = stuNewList.Except(stuOldList);
            foreach (Student s in differenceQuery)
                Console.WriteLine(s);
        }
    }
}

这是我的新更新的RemovedStudents方法:

public static void RemovedStudents(List<Student> stuNewList, List<Student> stuOldList)
    {
        GetStudentsOld().Except(GetStudentsNew());
        foreach (Student s in stuNewList)
            Console.WriteLine("student: {0} {1}", s.FirstName, s.LastName);
    }

这里是学生类(Student Class),虽然我没有编辑权限:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OldandNewStudents
{
public class Student
{
    // Sample Student class
    // Each student has a first name, a last name, a class year, and a rank 
    // that indicates academic ranking in the student body.

    public string ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string StudentYear { get; set; }
    public int StudentRank { get; set; }

    public Student(string idNumber, string firstName, string lastName, string studentYear, int studentRank)
    {
        ID = idNumber;
        FirstName = firstName;
        LastName = lastName;
        StudentYear = studentYear;
        StudentRank = studentRank;
    }


    public override string ToString()
    {
        return ID + " " + FirstName + " " + LastName + " " + StudentYear + " " + StudentRank;
    }
}
}

这是我的新加法方法,但我不确定为什么会出现重载错误:

public static List<Student> GetActualNewStudents(List<Student> oldStudents, List<Student> newStudents)
    {
        List<Student> actualNewStudents = new List<Student>();

        foreach (var student in oldStudents) {
            if (oldStudents[student].ID != newStudents[student].ID)
            {
                actualNewStudents.Add(newStudents[student]);
            }
        }

        return actualNewStudents;
    }

添加 简而言之,是 移除 的相反操作。只有在学生同时存在于两个集合中时,才会发生变化。至少,你应该能够使用这个方法实现 AddedStudents。 - Rob
@Rob 是的,我意识到了。但是我不太确定如何在添加的方法中进行更改。 - tstokes8040
请尝试自己解决问题。这只是简单地交换一些变量名,我们不是来为你做作业的。告诉我们你卡在哪里了,我们会帮助你解决问题,但如果你只是把作业任务复制粘贴给我们,并告诉我们老师要求什么,我们是不会做的。 - Rob
1
@Rob显然已经告诉你我卡住的地方,但你还没有帮助我哈哈。这只是任务的一小部分。我已经把所有东西都想通了,就差这个了。这就是我为什么要求帮助的原因。我尝试了删除方法,但效果不如我所预期,这就是我发帖的原因。 - tstokes8040
抱歉 - 我实际上误读了问题。我以为你的 AddedStudents 方法已经起作用,而你只是要求 RemovedStudents 的逻辑。你的 RemovedStudents 逻辑看起来很好。如果它不起作用,你将不得不查看 Student 的代码,并重写 EqualsGetHashCode() - Rob
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - jdweng
3个回答

0
你可以创建一个包含共同学生的第三个数组,然后对于所有不在其中的学生,在新学生数组中考虑一个新学生。
public static List<Student> GetActualNewStudents(List<Student> oldStudents, List<Stident> newStudents)
    {
        var actualNewStudents = new List<Student>();
        foreach (var item in newStudents)
        {
            if (!oldStudents.Contains(item))
                actualNewStudents.Add(item);

        }
        return actualNewStudents;
    }

你是如何实现它的?你可能在条件语句中忘记了 "!" 吗?编辑你的帖子,加上你的新类,这样我就可以检查它。(我忘记在结尾处输入返回值) - maugusto
我已经更新了上面的添加方法。如果我能正确处理错误,我相信那应该可以工作。有什么想法吗? - tstokes8040
O(n^2)方法。非常低效。考虑使用HashSet代替。 - Aron
@tstokes8040 特别提到了 List.Contains,它的时间复杂度为 O(n),并且被调用了 n 次。 - Aron
@maugusto 是的,昨晚我在尝试这个,但不知道如何将其与for循环结合使用。有示例吗? - tstokes8040
显示剩余6条评论

0

使用您拥有的两个列表的问题在于比较,例如Except扩展方法将使用IEquatable的默认实现。您有一个构造函数,但类定义未包含在内。如果字段和属性包含值类型,则应用逐字节比较。如果您有任何引用类型,则需要覆盖默认的Equals方法。如果您只有值类型字段,则以下代码应该可以工作。

补充:

GetStudentsNew().Except(GetStudentsOld());

已删除:

GetStudentsOld.Except(GetStudentsNew());

区别:

public diff(IEnumerable<Student> new, IEnumerable<Student> old)
{
    var both = new.AddRange(old); 
    var add = both.Except(new);
    return add.Except(old);
}

我应该指出,Console.WriteLine不会像你期望的那样工作,因为你传递的是一个引用类型,而不是将被转换为你期望的字符串类型。

我只需要执行 ShowStudents(GetStudentsNew().Except(GetStudentsOld())); 来打印结果吗? - tstokes8040
你能确认一下这个 RemoveStudents 方法是不是正确的?GetStudentsNew().Except(GetStudentsOld());foreach (Student s in stuNewList)Console.WriteLine("student: {0} {1}", s.FirstName, s.LastName); - tstokes8040
只需运行它并进行比较?我现在不在电脑旁,但它看起来是正确的。 - James Ralston
看起来它只显示了新列表,没有显示从旧列表中删除的人。唯一应该显示的人是鲍勃(在旧列表底部)。 - tstokes8040
获取新列表的所有内容 - tstokes8040
显示剩余7条评论

0

这个方法有效,帮我得到了需要的结果:

加法代码:

public static List<Student> GetActualNewStudents(List<Student> oldStudents, List<Student> newStudents)
    {
        //Show the new students
        List<Student> actualNewStudents = newStudents.Where(y => !oldStudents.Any(z => z.ID == y.ID)).ToList();

        return actualNewStudents;
    }

被删除学生的代码:

public static List<Student> GetActualRemovedStudents(List<Student> oldStudents, List<Student> newStudents)
    {
        //Show the removed students
        List<Student> actualRemovedStudents = oldStudents.Where(y => !newStudents.Any(z => z.ID == y.ID)).ToList();

        return actualRemovedStudents;
    }

修改代码:

public static List<Student> GetActualChangedStudents(List<Student> oldStudents, List<Student> newStudents)
    {
        //Show the changes
        List<Student> actualChangedStudents = newStudents.Where(y => !oldStudents.Any(z => z.FirstName == y.FirstName && z.LastName == y.LastName && z.StudentRank == y.StudentRank && z.StudentYear == y.StudentYear)).ToList();

        return actualChangedStudents;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接