Sam
Sam

Reputation: 30298

Finding IDs from a list that are not in another list in C#

I have two List<Guid>()s and I want to find GUID values that are not in the second list.

How do I do this using LINQ? I think LINQ would be a more efficient approach than a foreach().

Upvotes: 0

Views: 1704

Answers (2)

Jimi
Jimi

Reputation: 32248

I made a test, to compare the how much time different methods take to complete this task.

For the test, I used 2 List<Guid> of 200 items each.
The second list contains ~1/10 of pseudo-random elements which are also in the first one.

I measured the time each method required to complete using a StopWatch().

Since Except, Where and LookUp are cached, the test has been restarted each time. It can however be useful to know that the cached Functions take only a few Tick (1 ~ 7) to complete once initialized.
If the same query must be repeated multiple times, these Functions' feature can really make the difference.

This is how the two Lists are created:

static Random random = new Random();
// [...]

random.Next(0, 10);
List<Guid> guid1 = new List<Guid>(200);
List<Guid> guid2 = new List<Guid>(200);
int insertPoint = random.Next(0, 10);
for (int x = 0; x < 200; x++)
{
    guid1.Add(Guid.NewGuid());
    guid2.Add((x == insertPoint) ? guid1.Last() : Guid.NewGuid());

    if (x > 9 && ((x % 10F) == 0.0F))
        insertPoint = random.Next(x, x + 10);
}

These are the Functions tested:

List1 Except List2:

var result1 = guid1.Except(guid2);

List1.Item Where != List2.Item

var result2 = guid1.Where(guid1 => guid2.All(g => g != guid1));

List1.Items FindAll != List2.Items

var result3 = guid1.FindAll(g1 => guid2.All(g2 => g2 != g1));

List1.Item LookUp Contains (List2.Item)

var lookUpresult = guid1.ToLookup(g1 => guid2.Contains(g1));
var result4 = lookUpresult[false].ToList();

List1 Hashset GroupBy Contains (List2 Hashset)

var guidHS1 = new HashSet<Guid>(guid1);
var guidHS2 = new HashSet<Guid>(guid2);
var hsGroups = guid1.GroupBy(g => guidHS2.Contains(g));
var result5 = hsGroups.First().ToList();

ForEach List1->Item ForEach List2->Item (Item1 == Item2) => List3

List<Guid> guid3 = new List<Guid>();
bool found;
foreach (Guid guidtest in guid1) {
    found = false;
    foreach (Guid guidcompare in guid2) {
        if (guidtest == guidcompare) {
            found = true;
            break;
        }
    }
    if (!found) guid3.Add(guidtest);
}

These are the results of this test: (20 rounds)

Number of equal elements found: 181~184

EXCEPT          => Time: 1724 ~ 4356 ticks
WHERE           => Time: 3651 ~ 7360 ticks
FINDALL         => Time: 3037 ~ 6472 ticks
LOOKUP          => Time: 9406 ~ 16502 ticks
HASHSET GROUPBY => Time: 1773 ~ 3597 ticks
FOREACH         => Time: 650  ~ 1529 ticks

Upvotes: 1

Peter B
Peter B

Reputation: 24187

For that you can use the LINQ Except() extension method:

var result = list1.Except(list2);

Upvotes: 4

Related Questions