How to compare two List<String> to each other?

C#.Net

C# Problem Overview


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) 
{

}

C# Solutions


Solution 1 - C#

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

Solution 2 - C#

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)

Solution 3 - C#

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

Solution 4 - C#

    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());
    }

Solution 5 - C#

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);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNoWarView Question on Stackoverflow
Solution 1 - C#Mark ByersView Answer on Stackoverflow
Solution 2 - C#Tim SchmelterView Answer on Stackoverflow
Solution 3 - C#JYeltonView Answer on Stackoverflow
Solution 4 - C#Sunil ThakurView Answer on Stackoverflow
Solution 5 - C#Sai Kalyan Kumar AkshinthalaView Answer on Stackoverflow