1

Hi i have an issue while doing xoring between objects in c#. Suppose i have a class having below properties -

public string UserName { get; set; }
public bool IsUserEmployed { get; set; }
public bool IsUserValid { get; set; }`

I have 2 lists of this classes:

List<Class1> List1 = new List<Class1>();
List<Class1> List2 = new List<Class1>();

I tried the basic xoring as follows:

 FinalList.AddRange(List1.Except(List2));                  
 FinalList.AddRange(List2.Except(List1));`

But i didnt got the results in the FinalList as xor.

I want to perform xor on the List1 and List2 that could compare all the 3 properties in the objects in both the list and give me a 3rd list. Kindly Help.

Marco
  • 22,856
  • 9
  • 75
  • 124
mailmehere
  • 173
  • 1
  • 3
  • 14
  • 1
    First at all you should override `Equals` and `GetHashCode` for your class. This will allow you to compare objects. Check this post http://stackoverflow.com/questions/2363143/whats-the-best-strategy-for-equals-and-gethashcode – Uriil Jun 13 '14 at 06:02

4 Answers4

2

This is a solution scratched together in LinqPad. I have created a custom IEqualityComparerm, which can be reused at will. To use this comparer I am passing 2 arguments to the Except method: the second list and the comparer.

void Main()
{
    List<CustomObject> List1 = new List<CustomObject>() 
    {
        new CustomObject() {UserName ="1", IsUserEmployed = true, IsUserValid = false},
        new CustomObject() {UserName ="2", IsUserEmployed = true, IsUserValid = false},
        new CustomObject() {UserName ="3", IsUserEmployed = true, IsUserValid = false},
        new CustomObject() {UserName ="4", IsUserEmployed = true, IsUserValid = false}
    };
    List<CustomObject> List2 = new List<CustomObject>() 
    {
        new CustomObject() {UserName ="2", IsUserEmployed = true, IsUserValid = false},
        new CustomObject() {UserName ="3", IsUserEmployed = true, IsUserValid = false},

    };

    IEqualityComparer<CustomObject> CustomComparer = new CustomObjectEqualityComparer<CustomObject>();

    var xor = List1.Except(List2, CustomComparer).ToList().Dump();


}
public class CustomObject 
{
    public string UserName { get; set; }
    public bool IsUserEmployed { get; set; }
    public bool IsUserValid { get; set; }
}


public class CustomObjectEqualityComparer<T> : IEqualityComparer<CustomObject>
{
    public bool Equals(CustomObject t1, CustomObject t2)
    {
        if(t1.IsUserEmployed == t2.IsUserEmployed &&
           t1.IsUserValid ==t2.IsUserValid &&
           t1.UserName == t2.UserName)
       {
            return true;
       }

        return false;
    }

    public int GetHashCode(CustomObject _obj)
    {
        return _obj.IsUserEmployed.GetHashCode() + _obj.IsUserEmployed.GetHashCode() + _obj.IsUserValid.GetHashCode();
    }
}
public static class IEnumerableExtensions
{
  public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
  {
    foreach (T item in source)
      action(item);
  }
}

As a small note: This code does not check for null or other possible errors.

Marco
  • 22,856
  • 9
  • 75
  • 124
  • You are welcome. I just noted, that there is an ExtensionMethod for IEnumerable attached to use ForEach in a method syntax. Leftovers from my template, just ignore it. – Marco Jun 13 '14 at 07:02
1

You need to override the Equals method of your Class1.

Why? Because right now it is comparing for instances which I guess in your case will always return false.

public override bool Equals(Object obj)
{
    Class cs = (MyClass)obj;
    return UserName == cs.UserName && 
           IsUserEmployed  = cs.IsUserEmployed &&
           IsUserValid == cs.IsUserValid;
}

**You need to put some checks where obj is not null.

Nikhil Agrawal
  • 47,018
  • 22
  • 121
  • 208
0

Alternative implementation of fast xor IList collections

public static IList<T> ExclusiveOr<T>([NotNull]this IList<T> @this, IList<T> a)
{
    a = a ?? new T[]{};
    ISet<T> set = new HashSet<T>(@this);
    foreach (T current in a)
    {
        if (set.Contains(current))
        {
            set.Remove(current);
        }
        else
        {
            set.Add(current);
        }
    }
    return set.ToList();
}
S.Spieker
  • 7,005
  • 8
  • 44
  • 50
0

There is an extension for XOR, left XOR or right XOR between two lists : https://stackoverflow.com/a/45480272/2546739

You can use it with an IEqualityComparer or not, at your choice.

Xav987
  • 1,182
  • 1
  • 15
  • 17