Reto
Reto

Reputation: 181

How to write generic function processing two Lists holding any kind of objects?

I want to write a function that processs two Lists of the same objects. The function does always the same thing:

  1. Find the objects that are only in List2 but not in List1 -> Do something with them
  2. Find the object that are in both Lists -> Do something different with them.

Now the point is, that I have List pairs holding different kind of objects to which I want to apply this exact process. Example:

List<Foo1> L11, L12;
List<Foo2> L21, L22;
List<Foo3> L31, L32;

So how do I have to write the code, so that I do not have to repeat the code for each List type ?

Greetings and Thank you

Upvotes: 0

Views: 70

Answers (3)

DmitryG
DmitryG

Reputation: 17850

Your can use the Except/Intersect Linq methods as follows:

void Process<T>(IList<T> list1, IList<T> list2, IEqualityComparer<T> comparer = null) {
    //Find the objects that are only in List2 but not in List1 
    foreach(var item in list2.Except(list1, comparer)) {
        // -> Do something with them
    }
    //Find the object that are in both Lists -> Do something different with them.
    foreach(var item in list1.Intersect(list2, comparer)) {
        // -> Do something different with them.
    }
}

Upvotes: 1

vgru
vgru

Reputation: 51204

LINQ already provides two methods which do this:

// get all members of L11 not present in L12
var except = L11.Except(L12).ToList();

// get members present in both lists
var intersect = L11.Intersect(L12).ToList();

These overloads will use the default comparer for the list element type, so since you want to compare custom classes, you will need to use the overload which accepts a custom IEqualityComparer<T>:

var comparer = new CustomComparer();
var except = L11.Except(L12, comparer).ToList();
var intersect = L11.Intersect(L12, comparer).ToList();

which you need to write yourself:

class CustomComparer : IEqualityComparer<SomeClass>
{
    public bool Equals(SomeClass x, SomeClass y)
    {
        // return true if equal
    }

    public int GetHashCode(SomeClass obj)
    {
        // return a hash code for boj
    }
}

Upvotes: 1

Paweł Dyl
Paweł Dyl

Reputation: 9143

I would prepare a method, like below:

static void Process<T>(IEnumerable<T> list1, IEnumerable<T> list2, Action<T> onlyIn2, Action<T> inBoth)
{
    var hash = new HashSet<T>(list1);
    foreach (var item2 in list2)
        if (hash.Contains(item2))
            inBoth(item2);
        else
            onlyIn2(item2);
}

You can then use it as follows:

var list1 = new List<int> {1, 2, 3, 4, 5};
var list2 = new List<int> {3, 4, 5, 6};
Process(list1, list2, a =>
{
    Console.WriteLine("{0} only in 2", a);
}, a =>
{
    Console.WriteLine("{0} in both", a);
});

Note that it uses standard comparison rules (for objects reference equality unless Equals is overrided or IEqualityComparer<TKey> is implemented).

Upvotes: 1

Related Questions