比较两个列表C#

时间:2016-08-30 15:51:30

标签: c# list compare

好吧,所以我试图比较两个列表和一个方法来显示第二个列表中的新项目。这些列表是硬编码的,并以不同的方法在控制台上打印出来。我设法能够从两个列表中提取每个条目的唯一方法是使用foreach循环,但它总是指向每个条目不相等的语句,即使条目完全相同。我不确定为什么会这样。

以下是两个编码列表

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

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

    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 StudentIDMatch(List<Student> students, List<Student> student)
    {


        foreach (var ID in students)
        {
            bool isMatch = false;
            do

                foreach (var ID2 in student)
                {
                    if (ID2 != ID)
                    {

                        isMatch = false;
                    }
                    else if (ID.Equals(ID2))
                    {
                        isMatch = false;
                    }
                }
            while (!isMatch);

        }
    }

最终我试图找出差异并打印出来。我知道它不完整但我需要弄清楚如何在我开始解决如何打印它们之前正确地比较它们。此外,我知道Do While循环不正确,我需要在修复后再重做。

谢谢!

4 个答案:

答案 0 :(得分:1)

首先,

出现了错误
else if (ID.Equals(ID2))
                    {
                        isMatch = false;
                    }

你可能意味着isMatch = true;

也就是说,.NET Framework提供了大量工具来比较两个列表。

如果你想要的是在第二个列表中提取新项目,你可以使用这样的东西: students1.Where(student1 => !students2.Any(student2 => student2 != student1)).ToList();

如果你的目标是将学生从一个列表中隔离出来,而不是在另一个列表中,那么你可以做两次并加入结果。这是我能提供的最简单,最快捷的解决方案。 除非你想花时间制作自己的算法。您仍然可以利用此框架。

答案 1 :(得分:0)

如果你只是在ID上进行匹配,那么你可以这样做:

List<int> newStudentsList = newStudents.Select(n => n.Id).ToList();
List<int> oldStudentsList = oldStudents.Select(o => o.Id).ToList();

var missingStudents = oldStudentsList.Except(newStudentsList).ToList();

这是从每个原始列表中构建Id的列表,然后创建一个存在于一个而不存在于其中的所有Id的新列表。

答案 2 :(得分:0)

如果每个学生都有唯一标识符,您可以在Student课程中覆盖以下两种方法:

public override bool Equals(object obj)
{
    return ID == (obj as Student).ID;
}

public override int GetHashCode()
{
    return ID;
}

然后找到这样的差异:

var diff = GetStudentsNew().Except(GetStudentsOld()).ToList();

答案 3 :(得分:0)

我已经列出了几种可以实现收集比较的方法。有一点需要注意:如果先前对集合进行了排序,那么比较会更快。

internal class Program
{
    private static void Main(string[] args)
    {
        var oldStudents = GetStudentsOld();
        var newStudents = GetStudentsNew();

        Console.WriteLine("Using 'Except' with 'IEqualityComparer<Student>'");
        WriteDropOutsWithExcept(oldStudents, newStudents);
        Console.WriteLine();
        WriteNewStudentsWithExcept(oldStudents, newStudents);
        Console.WriteLine("********************************************************");
        Console.WriteLine();

        Console.WriteLine("Using 'Compare' linq with 'Key' selector");
        WriteDropOutsWithKey(oldStudents, newStudents);
        Console.WriteLine();
        WriteNewStudentsWithKey(oldStudents, newStudents);
        Console.WriteLine("********************************************************");
        Console.WriteLine();

        Console.WriteLine("Using 'Compare' linq with 'StrategyComparer<Student>'");
        WriteDropOutsWithStrategyComparer(oldStudents, newStudents);
        Console.WriteLine();
        WriteNewStudentsWithStrategyComparer(oldStudents, newStudents);

        Console.ReadKey();
    }

    private static void WriteDropOutsWithExcept(List<Student> oldStudents, List<Student> newStudents)
    {
        Console.WriteLine("Dropped from enrollment:");
        foreach (var student in oldStudents.Compare(newStudents, new StudentComparer()))
        {
            Console.WriteLine(student);
        }
    }

    private static void WriteNewStudentsWithExcept(List<Student> oldStudents, List<Student> newStudents)
    {
        Console.WriteLine("Added to enrollment:");
        foreach (var student in newStudents.Compare(oldStudents, new StudentComparer()))
        {
            Console.WriteLine(student);
        }
    }

    private static void WriteDropOutsWithKey(List<Student> oldStudents, List<Student> newStudents)
    {
        Console.WriteLine("Dropped from enrollment:");
        foreach (var student in oldStudents.Compare(newStudents, s => s.Id))
        {
            Console.WriteLine(student);
        }
    }

    private static void WriteNewStudentsWithKey(List<Student> oldStudents, List<Student> newStudents)
    {
        Console.WriteLine("Added to enrollment:");
        foreach (var student in newStudents.Compare(oldStudents, s => s.Id))
        {
            Console.WriteLine(student);
        }
    }

    private static void WriteDropOutsWithStrategyComparer(List<Student> oldStudents, List<Student> newStudents)
    {
        Console.WriteLine("Dropped from enrollment:");
        foreach (var student in oldStudents.Compare(newStudents, new StrategyComparer<Student, int>(k => k.Id)))
        {
            Console.WriteLine(student);
        }
    }

    private static void WriteNewStudentsWithStrategyComparer(List<Student> oldStudents, List<Student> newStudents)
    {
        Console.WriteLine("Added to enrollment:");
        foreach (var student in newStudents.Compare(oldStudents, new StrategyComparer<Student, int>(k => k.Id)))
        {
            Console.WriteLine(student);
        }
    }

    private class StudentComparer : IEqualityComparer<Student>
    {
        public bool Equals(Student x, Student y)
        {
            return x.Id == y.Id;
        }

        public int GetHashCode(Student obj)
        {
            return obj.Id.GetHashCode();
        }
    }

    private class StrategyComparer<TModel, TKey> : IStrategyComparer<TModel>
    {
        private readonly Func<TModel, TKey> _keySelector;

        public StrategyComparer(Func<TModel, TKey> keySelector)
        {
            _keySelector = keySelector;
        }

        public bool Equals(TModel x, TModel y)
        {
            return Equals(_keySelector(x), _keySelector(y));
        }

        public int GetHashCode(TModel obj)
        {
            return _keySelector(obj).GetHashCode();
        }
    }
}

internal interface IStrategyComparer<in TModel> : IEqualityComparer<TModel>
{
}

public static class CollectionUtils
{
    //  Compare using Linq
    public static IEnumerable<TModel> Compare<TModel, TKey>(this IEnumerable<TModel> source1,
        IEnumerable<TModel> source2, Func<TModel, TKey> key)
    {
        return source1.Where(model => !source2.Any(m => Equals(key(m), key(model))));
    }

    //  Compare using Except/Except with comparer
    public static IEnumerable<TModel> Compare<TModel>(this IEnumerable<TModel> source1, IEnumerable<TModel> source2,
        IEqualityComparer<TModel> comparer = null)
    {
        if (comparer == null)
        {
            return source1.Except(source2);
        }

        return source1.Except(source2, comparer);
    }

    //  Compare using Linq with StrategyComparer
    public static IEnumerable<TModel> Compare<TModel>(this IEnumerable<TModel> source1,
        IEnumerable<TModel> source2, IStrategyComparer<TModel> comparer) {
        return source1.Where(model => !source2.Any(m => comparer.Equals(model, m)));
    }
}

输出:

  

在'IEqualityComparer'中使用'Except'   掉了   招生:
  [150] Stephenson,Bob :: Junior(211)

     

添加到注册:
  [53] Mortensen,Sven :: Freshman(311)
  [60] Tucker,Lance :: Junior(411)

           

使用'比较'linq和'Key'选择器
  退出注册:
  [150] Stephenson,Bob :: Junior(211)

     

添加到注册:
  [53] Mortensen,Sven :: Freshman(311)
  [60] Tucker,Lance :: Junior(411)

           

使用'比较'linq和'StrategyComparer'
  掉了   招生:
  [150] Stephenson,Bob :: Junior(211)

     

添加到注册:
  [53] Mortensen,Sven :: Freshman(311)
  [60] Tucker,Lance :: Junior(411)