Sobhan
Sobhan

Reputation: 1061

What is the most efficient way to find elements in a list that do not exist in another list and vice versa?

Consider you have two lists in C#, first list contains elements of TypeOne and second list contains elements of TypeTwo:

TypeOne
{  
    int foo;  
    int bar;  
}

TypeTwo
{  
    int baz;  
    int qux;  
}

Now I need to find elements ( with some property value ) in the first list that don't exist in the second list, and similarly I want to find elements in the second list that don't exist in the first list. (There are only zero or one occurences in either lists.)

What I tried so far is to iterate both lists like this:

foreach (var item in firstList)
{
    if (!secondList.Any(a=> a.baz == item.foo)
    {
        // Item is in the first list but not in second list.
    }
}

and again:

foreach (var item in secondList)
{
    if (!firstList.Any(a=> a.foo == item.baz)
    {
        // Item is in the second list but not in first list.
    }
}

I hardly think this is a good way to do what I want. I'm iterating my lists two times and use Any in each of them which also iterates the list. So too many iterations.

What is the most efficient way to achieve this?

Upvotes: 0

Views: 435

Answers (2)

Toxantron
Toxantron

Reputation: 2398

I am afraid there is no prebuild solution for this, so the best we can do is optimize as much as possible. We only have to iterate the first list, because everything that is in second will be compared already

// First we need copies to operate on
var firstCopy = new List<TypeOne>(firstList);
var secondCopy = new List<TypeTwo>(secondList);

// Now we iterate the first list once complete
foreach (var typeOne in firstList)
{
    var match = secondCopy.FirstOrDefault(s => s.baz == typeOne.foo);
    if (match == null)
    {
        // Item in first but not in second
    }
    else
    {
        // Match is duplicate and shall be removed from both
        firstCopy.Remove(typeOne);
        secondCopy.Remove(match);
    }
}

After running this both copies will only contain the values which are unique in this instance. This not only reduces it to half the number of iterations but also constantly improves because the second copy shrinks with each match.

Upvotes: 2

VVN
VVN

Reputation: 1610

Use this LINQ Query.

  var result1 = secondList.Where(p2 => !firstList.Any(p1 => p1.foo == p2.baz));

  var result2=firstList.Where(p1=> !secondList.Any(p2=> p2.foo == p1.baz);

Upvotes: 1

Related Questions