0

I have two Lists that I'm trying to compare. What I need to accomplish is essentially to remove the items that are duplicated between the two lists and only keep the objects that are different. Right now, I'm inserting the non-duplicate data into a new list.

The data I'm using here...

LIST1 ("b",2) ("c",3)

LIST2 ("a",1) ("b",2) ("c",3) ("d",4)

NEWLIST ("a",1) ("d",4)

Here's what I have so far...

My object:

public class TestClass
{
    protected string teststring;
    protected int testint;

    public string TestString
    {
        get { return teststring; }
        set { teststring = value; }
    }
    public int TestInt
    {
        get { return testint; }
        set { testint = value; }
    }

    public TestClass() { }
}

My compare logic:

private static List<TestClass> CompareCodes(List<TestClass> list1, List<TestClass> list2)
{
    List<TestClass> newList = new List<TestClass>();
    foreach (TestClass s in list2)
    {
        if (list1.Contains(s) == false)
        {
            newList.Add(s);
        }
    }        

    if (newList.Count != 0)
        return newList;
    else
        return null;
}

The new list will be used to insert data into a database table. If it's null, no action will be taken. I'm using .NET 2.0 in this app (it's an enhancement to an older app), so I can't use LINQ. So is there any other way to make this work that I'm missing? Or is there a better way to do this? I haven't been able to find anything (maybe just not looking hard enough) to accomplish what I'm trying to do.

Thanks in advance!

LDWisdom
  • 111
  • 3
  • 16
  • There isn't any better way. Just remove the last `if` statement, `newList` will never be `null`, also, you must override `Equals` and `GetHashCode` in `TestClass` – Ahmed KRAIEM Dec 04 '13 at 16:18
  • Instead of removing that last `if` check, you should change the statement to look for `if (newList.Count != 0)` – Sven Grosen Dec 04 '13 at 16:19
  • I think that returning an empty list is better than returning null. – Ahmed KRAIEM Dec 04 '13 at 16:22
  • Yeah, I actually did that in my app after I posted this once I realized that. So that part is already fixed. Thanks! – LDWisdom Dec 04 '13 at 16:25

3 Answers3

3

So you're almost there, but you'll need to override the Equals method on your class to make it work:

public class TestClass
{
    public override bool Equals(object y)
    {
        TestClass newY = y as TestClass;
        if (newY == null) { return false; }

        return newY.TestString == this.TestString &&
            newY.TestInt == this.TestInt;
    }

    public override int GetHashCode()
    {
        unchecked // Overflow is fine, just wrap
        {
            int hash = 17;

            // Suitable nullity checks etc, of course :)
            hash = hash * 23 + this.TestInt.GetHashCode();
            hash = hash * 23 + this.TestString == null ?
                0 :
                this.TestString.GetHashCode();
            return hash;
        }
    }
}

Use Jon Skeet's answer here to implement your hash code.

Community
  • 1
  • 1
Mike Perrenoud
  • 66,820
  • 29
  • 157
  • 232
  • he is using .net 2.0 did you read the question var is in .net 3.0 – BRAHIM Kamel Dec 04 '13 at 16:19
  • @Ric, that interface is probably not available to the OP considering the version of the framework they are using (I'll check). But further, even with `IEquatable` you need to implement these two methods. – Mike Perrenoud Dec 04 '13 at 16:19
  • @JulieShannon, yeah I read the question; that's why I didn't use LINQ. Using `var` is just a habit now. – Mike Perrenoud Dec 04 '13 at 16:20
  • I was only going for `IEquatable` as there is only one method to implement, `Equals(T other)` so it's more generic etc. And it's available for .net 2 http://msdn.microsoft.com/en-US/library/ms131190(v=vs.80).aspx – Ric Dec 04 '13 at 16:26
  • @Ric, I did notice it's available. But remember this, `IEquatable` isn't enough. There isn't a huge adoption of consumers of that interface. You still need to override `Equals` and `GetHashCode`. – Mike Perrenoud Dec 04 '13 at 16:28
  • @MichaelPerrenoud fair enough :) – Ric Dec 04 '13 at 16:31
  • @MichaelPerrenoud so stupid question...how do I actually implement this into my CompareCodes function? I was looking at something similar to what JulieShannon answered because I would have to get the object out of each list in order to compare them. So my thought was "if(s.Equals(t))", or am I still missing something? – LDWisdom Dec 04 '13 at 16:40
  • @LDWisdom take a look at my answer below that shows you how to merge that code into your TestClass – Mauricio Gracia Gutierrez Dec 04 '13 at 16:50
  • @LDWisdom, just literally paste the code I've provide into your class. Now, the `GetHashCode` implementation, you need to grab that from the Jon Skeet answer I provided. If you give me a couple minutes I can show you how it would fit into your class. – Mike Perrenoud Dec 04 '13 at 17:01
  • @LDWisdom, and you don't actually change the `CompareCodes` method. The problem with the `Contains` call is it will *always* return `false`. You have to *override* the equality operation for your class. The code I provided goes in the `TestClass`. – Mike Perrenoud Dec 04 '13 at 17:04
  • @MichaelPerrenoud OK, this is starting to make more sense to me. Thanks for the help! I'll try this out and see how it works. :) – LDWisdom Dec 04 '13 at 17:16
  • @MauricioGracia thanks for your help too! Seeing it all out there helped it make more sense to me. – LDWisdom Dec 04 '13 at 17:17
3

In the code that you have provided you are only keeping the items of list2 that are not in list1. but how about the items that are in list1 but not in list2 ? and since you mention

What I need to accomplish is essentially to remove the items that are duplicated between the two lists and only keep the objects that are different

This code belows returns a new list with the items that are unique in both lists

private static List<TestClass> CompareCodes(List<TestClass> list1, List<TestClass> list2)
{
    List<TestClass> newList ;

    newList = new List<TestClass>();

    //All the items in list1 that are not in list2 are added
    foreach (TestClass s in list1)
    {
        if ( ! list2.Contains(s))
        {
            newList.Add(s);
        }
    }        

    //All the items in list2 that are not in list1 are added
    foreach (TestClass s in list2)
    {
        if ( ! list1.Contains(s))
        {
            newList.Add(s);
        }
    }        

    return newList;
}

And in your class

public class TestClass implements IEquatable
{
    protected string teststring;
    protected int testint;

    public string TestString
    {
        get { return teststring; }
        set { teststring = value; }
    }
    public int TestInt
    {
        get { return testint; }
        set { testint = value; }
    }
    public override bool Equals(object y)
    {
        TestClass newY = y as TestClass;
        if (newY == null) { return false; }
        return newY.TestString == this.TestString &&
            newY.TestInt == this.TestInt;
    }
    public override int GetHashCode()
    {
        // use this example or implement some hash code logic
        return this.TestInt.GetHashCode() ;
    }
    public TestClass() { }
}
Mauricio Gracia Gutierrez
  • 10,288
  • 6
  • 68
  • 99
0
private static List<TestClass> CompareCodes(List<TestClass> list1,
    List<TestClass> list2)
{
    List<TestClass> newList = new List<TestClass>();
    bool found = false; 
    foreach (TestClass s in list2)
    {
        foreach (TestClass t in list1)
        {   
           //let's say that teststring is your object id / key 
            if(s.TestString==t.TestString )
            { 
                found = true; 
                break; 
            }
        }

        if(!found)         
            newList.Add(s);               

       found=false;  
   }
  // do the something for the List1 
    foreach (TestClass s in list1)
    {
        foreach (TestClass t in list2)
        {   
           //let's say that teststring is your object id / key 
            if(s.TestString==t.TestString )
            { 
                found = true; 
                break; 
            }
        }

        if(!found)         
            newList.Add(s);               

       found=false;  
     }



   if (newList != null)
       return newList;
   else
       return null;
}
BRAHIM Kamel
  • 13,492
  • 1
  • 36
  • 47