6

What is the fastest and best way to compare 2 lists and return a match. Only one match is possible. List1 contains dynamic data from a database.

The way I do it now :

foreach (var item1 in List1)
{
   foreach (var item2 in List2 )
   {
       if(item2 == item1)
       string match = item1;
   }
}

I have a feeling like it can be done a lot faster.

Bernardmoes
  • 340
  • 1
  • 3
  • 13

3 Answers3

13

Use Enumerable.Intersect.

var matchItem = List1.Intersect(List2).First();

Not really sure how much it is faster to your current code, you can measure it using Stopwatch. But in your current code you should break your inner as well as outer loop on finding the match. Something like:

foreach (var item1 in List1)
{
    string match = null;
    foreach (var item2 in List2)
    {
        if (item2 == item1)
        {
            match = item1;
            break;
        }
    }
    if (match != null)
        break;
}
Habib
  • 219,104
  • 29
  • 407
  • 436
  • @Habib, is it faster or concise? i mean does it internally do the same lopping ? – tariq May 08 '13 at 07:42
  • @tariq, yes it does the looping internally, I am not sure if it s faster, that is why I provided the other option with the modified code from the question. – Habib May 08 '13 at 07:43
  • 2
    The Linq will be slower on average because it will keep iterating even after it's found a match. The second code sample will be fastest. – Matthew Watson May 08 '13 at 07:43
  • @MatthewWatson, yes that is correct, since `Intersect` will gather all the intersecting elements first and then applying `First` – Habib May 08 '13 at 07:53
  • This isn't as fast as it could be. It is doing an extra comparison of `match != null` inside the outer loop. If you just return from the inner loop you will avoid doing that comparison in the outer loop on every iteration of the outer loop. (See my answer, for example.) Given that the question asks for "the fastest way", this isn't quite the fastest. – Matthew Watson May 08 '13 at 08:07
  • for more elaboration on Performance see : https://stackoverflow.com/a/20767645/5703033 – Yonatan Tuchinsky Oct 23 '18 at 12:59
2

You have many ways to do this. It mostly depends on the data you're trying to match.

  • First thing you can do is having a sorted list
  • then if you know the middle value of the list you can iterate through your list from the beginning of from the end
  • but mostly just return your value since you've found it

also the first 2 points will only work if your list has some numeric value on which you can rely to identify an item.

The first optimization you can do is:

Foreach (var item1 in List1)
{
   Foreach (var item2 in List2 )
   {
       if(item2 == item1) return item1;
   }
}

If you really need this routine to be very fast you'll have to do optimizations based on the data that is in your lists.

Also if your data is string in both lists, you can generate an hashcode for each string (string.GetHashCode) and then rely on the hascode to sort and search in your lists.

There are many other ways, but it all depends on:

  • the amount of data you have in your lists (if you only have 100 elements you won't see a lot of performance gains)
  • if your lists are static or dynamic
  • how often they can change if they are dynamic
  • how often do you make a search in these lists
  • ...
ppetrov
  • 3,077
  • 2
  • 15
  • 27
2

You can short-circuit the loops when you find any matches. You could then use a method that returns the item that matches, or null if none matched (assuming the elements are references types):

foreach (var item1 in List1)
    foreach (var item2 in List2)
        if (item2 == item1)
            return item1;

return null;
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276