0

Alright, so I'm trying to compare two lists with a method to display the new items in the second list. The lists are hard coded in and in separate methods to print out on the console. The only way I've managed to be able to pull every entry from both lists is using a foreach loop but it always goes to the statement that each entry is not equal even when the entries are the exact same. I'm not sure why this happening.

Here are the two coded lists

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

and here is the method I've tried to compare the two lists

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

        }
    }

ultimately I'm trying to find the differences and print them out. I know it's not complete but I need to figure out how to compare them correctly before I start to tackle how to get them printed out. Also I know the Do While loop isn't correct and I need to redo that as well after this gets fixed.

Thanks!

4 Answers4

2

First, there is a mistake in

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

You probably meant isMatch = true;

That said, the .NET Framework provide plenty of tools to compare two lists.

If what you want is to extract the new items in the second list, you could use something like this : students1.Where(student1 => !students2.Any(student2 => student2 != student1)).ToList();

If your goal is to isolate the students from one list that aren't in the other list both ways, you can do it twice and join the results. It's the easiest and quickest solution I could come with. Unless you want to take the time to make your own algorithm. You can still leverage the framework for this.

1

I've laid out several ways you can achieve collection comparisons. One thing to note: if collections are sorted prior, the comparisons will be faster.

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

Output:

Using 'Except' with 'IEqualityComparer'
Dropped from enrollment:
[150] Stephenson, Bob :: Junior (211)

Added to enrollment:
[53] Mortensen, Sven :: Freshman (311)
[60] Tucker, Lance :: Junior (411)


Using 'Compare' linq with 'Key' selector
Dropped from enrollment:
[150] Stephenson, Bob :: Junior (211)

Added to enrollment:
[53] Mortensen, Sven :: Freshman (311)
[60] Tucker, Lance :: Junior (411)


Using 'Compare' linq with 'StrategyComparer'
Dropped from enrollment:
[150] Stephenson, Bob :: Junior (211)

Added to enrollment:
[53] Mortensen, Sven :: Freshman (311)
[60] Tucker, Lance :: Junior (411)

IAbstract
  • 19,551
  • 15
  • 98
  • 146
0

If you're doing the match on the ID alone then you can do something like this:

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

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

That is building up a list of the Id's from each original list, then creating a new list of all the Id's that exist in one but not the other.

davemire
  • 1
  • 1
  • 4
0

If each student has a unique identifier, you can override the following two methods in your Student class:

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

public override int GetHashCode()
{
    return ID;
}

And then find the differences like this:

var diff = GetStudentsNew().Except(GetStudentsOld()).ToList();
Marximus
  • 61
  • 1
  • 3