100

Let's say there are

List<string> a1 = new List<string>();

List<string> a2 = new List<string>();

Is there way to do like this?

if (a1 == a2) 
{

}
Oded
  • 489,969
  • 99
  • 883
  • 1,009
NoWar
  • 36,338
  • 80
  • 323
  • 498

5 Answers5

184

If you want to check that the elements inside the list are equal and in the same order, you can use SequenceEqual:

if (a1.SequenceEqual(a2))

See it working online: ideone

John Cummings
  • 1,949
  • 3
  • 22
  • 38
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • Don't forget you could also implement your own `IEqualityComparer` and provide it as second argument (e.g. [a IgnoreCase comparer for string](http://msdn.microsoft.com/en-us/library/system.stringcomparer.currentcultureignorecase.aspx)). – Oliver Mar 07 '12 at 13:54
  • @MarkByers, when I am trying the SequenceEqual() in my system, why its throwing an exception like List does not contain a definition for 'SequenceEqual' and no extension method 'SequenceEqual' accepting a first argument of type...... – Sai Kalyan Kumar Akshinthala Mar 07 '12 at 14:08
  • 1
    @SaiKalyanAkshinthala: First that looks more like a compiler error than an exception. Ensure that you are using .NET 3.5 or newer and that you have a `using System.Linq` directive. Also look at the ideone link I posted to see a fully working example. You should be able to copy and paste it into your IDE and run it. – Mark Byers Mar 07 '12 at 14:17
  • 1
    I know this is an incredibly late comment, but I feel it should be important to note that this will throw an exception if one of the lists is `null`. – Wes Thompson Dec 08 '18 at 02:39
  • I found a case where this doesn't work. Somehow the PUBLIC Items of my lists are identical and have the same Count. However the PRIVATE items differ : There's an extra null item in one of them. I don't know why (I specifically generated the list with .Where(item => item != null). This private difference makes SequenceEqual return false. – jeancallisti Sep 01 '21 at 15:27
34

You could also use Except(produces the set difference of two sequences) to check whether there's a difference or not:

IEnumerable<string> inFirstOnly = a1.Except(a2);
IEnumerable<string> inSecondOnly = a2.Except(a1);
bool allInBoth = !inFirstOnly.Any() && !inSecondOnly.Any();

So this is an efficient way if the order and if the number of duplicates does not matter(as opposed to the accepted answer's SequenceEqual). Demo: Ideone

If you want to compare in a case insentive way, just add StringComparer.OrdinalIgnoreCase:

a1.Except(a2, StringComparer.OrdinalIgnoreCase)
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • 14
    Two potential problems with using `Except` : It will only returns items of `a1` that do not exist in `a2` - so if `a2` contained extra items this will return a false negative. Secondly, it does not account for duplication of the same item, only existence. Still a powerful tool, just needs to be used carefully. – Andrew Hanlon Mar 07 '12 at 23:58
  • 5
    @AndrewHanlon: i was reminded of this answer and your comment, so i have added some extra information and a way to check in both directions - 8.5 years later :D – Tim Schmelter Dec 17 '20 at 22:17
16

I discovered that SequenceEqual is not the most efficient way to compare two lists of strings (initially from http://www.dotnetperls.com/sequenceequal).

I wanted to test this myself so I created two methods:

    /// <summary>
    /// Compares two string lists using LINQ's SequenceEqual.
    /// </summary>
    public bool CompareLists1(List<string> list1, List<string> list2)
    {
        return list1.SequenceEqual(list2);
    }

    /// <summary>
    /// Compares two string lists using a loop.
    /// </summary>
    public bool CompareLists2(List<string> list1, List<string> list2)
    {
        if (list1.Count != list2.Count)
            return false;

        for (int i = 0; i < list1.Count; i++)
        {
            if (list1[i] != list2[i])
                return false;
        }

        return true;
    }

The second method is a bit of code I encountered and wondered if it could be refactored to be "easier to read." (And also wondered if LINQ optimization would be faster.)

As it turns out, with two lists containing 32k strings, over 100 executions:

  • Method 1 took an average of 6761.8 ticks
  • Method 2 took an average of 3268.4 ticks

I usually prefer LINQ for brevity, performance, and code readability; but in this case I think a loop-based method is preferred.

Edit:

I recompiled using optimized code, and ran the test for 1000 iterations. The results still favor the loop (even more so):

  • Method 1 took an average of 4227.2 ticks
  • Method 2 took an average of 1831.9 ticks

Tested using Visual Studio 2010, C# .NET 4 Client Profile on a Core i7-920

JYelton
  • 35,664
  • 27
  • 132
  • 191
  • It's not a fair comparison for two reasons: 1. Equals is not used, 2. It only works for lists, which is OK though for this question. – mycroes Sep 19 '14 at 11:24
  • If list2 has the same items as list1, but also has one more item than list1, won't this still return true? Do you have to do a second loop through list2 and do the same comparison? – Peter Tirrell Jul 27 '20 at 20:36
  • 1
    @PeterTirrell No, because it compares the `.Count` property first. – JYelton Jul 27 '20 at 21:26
  • @JYelton ah yeah, my bad. I realized that after the fact, my unit test I was using had another flaw in it. Thanks! – Peter Tirrell Jul 28 '20 at 12:33
1
    private static bool CompareDictionaries(IDictionary<string, IEnumerable<string>> dict1, IDictionary<string, IEnumerable<string>> dict2)
    {
        if (dict1.Count != dict2.Count)
        {
            return false;
        }

        var keyDiff = dict1.Keys.Except(dict2.Keys);
        if (keyDiff.Any())
        {
            return false;
        }

        return (from key in dict1.Keys 
                let value1 = dict1[key] 
                let value2 = dict2[key] 
                select value1.Except(value2)).All(diffInValues => !diffInValues.Any());
    }
Sunil Thakur
  • 97
  • 2
  • 11
-1

You can check in all the below ways for a List

List<string> FilteredList = new List<string>();
//Comparing the two lists and gettings common elements.
FilteredList = a1.Intersect(a2, StringComparer.OrdinalIgnoreCase);
  • 2
    I didn't down vote - but your answer doesn't actually address the OP's question. It produces an intersection, so you'll need to do an additional step to check if that intersection matches `a1` and `a2`. – RichK Mar 07 '12 at 15:45
  • 2
    Also, Intersect will throw out duplicates, so this is only going to check the distinct elements in `a1` and `a2`. – RichK Mar 07 '12 at 16:23