Thorin Oakenshield
Thorin Oakenshield

Reputation: 14692

Comparing Arrays using LINQ in C#

I've two arrays like

string[] a = { "a", "b", "c" };
string[] b = { "a", "b", "c" };

I need to compare the two arrays using LINQ.

The comparison should take place only if both arrays have same size. The data can be in any order and still return true if all values of a[] and all values of b[] are the same.

Upvotes: 25

Views: 41484

Answers (6)

Timur Lemeshko
Timur Lemeshko

Reputation: 2879

This works correctly with duplicates and check each element

a.Length == b.Length && !a.Where((t, i) => t != b[i]).Any()

Upvotes: 4

Arjen Stins
Arjen Stins

Reputation: 31

IDictionary<int, object> a = new Dictionary<int, object>();
IDictionary<int, object> b = new Dictionary<int, object>();
a.Add(1, "1");
a.Add(2, 2);
a.Add(3, "3");

b.Add(3, "3");
b.Add(1, "1");
b.Add(2, 2);

Console.WriteLine(a.All(i => b.Contains(i)) && b.All(i => a.Contains(i)));

Upvotes: 3

Handcraftsman
Handcraftsman

Reputation: 6993

if order doesn't matter or there can be duplicates, then perhaps:

public static class IEnumerableExtensions
{
    public static bool HasSameContentsAs<T>(this ICollection<T> source,
                                            ICollection<T> other)
    {
        if (source.Count != other.Count)
        {
            return false;
        }
        var s = source
            .GroupBy(x => x)
            .ToDictionary(x => x.Key, x => x.Count());
        var o = other
            .GroupBy(x => x)
            .ToDictionary(x => x.Key, x => x.Count());
        int count;
        return s.Count == o.Count &&
               s.All(x => o.TryGetValue(x.Key, out count) &&
                          count == x.Value);
    }
}

usage:

string[] a = { "a", "b", "c" };
string[] b = { "c", "a", "b" };

bool containSame = a.HasSameContentsAs(b);

some use cases:

  • different lengths (expect false)

    string[] a = { "a", "b", "c" };
    string[] b = { "b", "c" };
    
  • different order (expect true)

    string[] a = { "a", "b", "c" };
    string[] b = { "b", "c", "a" };
    

also works if the inputs can contain duplicate items, though it isn't clear from the question whether that characteristic is desired or not, consider:

  • duplicated items have same count (expect true)

    string[] a = { "a", "b", "b", "c" };
    string[] b = { "a", "b", "c", "b" };
    
  • duplicated items with different counts (expect false)

    string[] a = { "a", "b", "b", "b", "c" };
    string[] b = { "a", "b", "c", "b", "c" };
    

Upvotes: 4

Niki
Niki

Reputation: 15867

I think this will always be an O(n log n) operation, so I'd just sort both arrays and compare them e.g. using SequenceEqual.

Upvotes: 5

Jeremy Roberts
Jeremy Roberts

Reputation: 1208

Not sure about the performance, but this seems to work.

string[] a = { "a", "b", "c" };
string[] b = { "a", "b", "c" };

bool result = a.SequenceEqual(b);
Assert.AreEqual(true, result);

However, it is not order independent so it does not fulfill the OP's requirement.

string[] a = { "a", "b", "c" };
string[] b = { "a", "c", "b" };

bool result = a.SequenceEqual(b);
Assert.AreEqual(false, result);

Upvotes: 27

Kyle Rosendo
Kyle Rosendo

Reputation: 25287

string[] a = { "a", "b" };
string[] b = { "a", "b" };

return (a.Length == b.Length && a.Intersect(b).Count() == a.Length);

After some performance testing:

  • Over 10,000 small strings - 5ms
  • Over 100,000 small strings - 99ms
  • Over 1,000,000 small strings - Avg. 601ms
  • Over 100,000 ~500 character strings - 190ms

Upvotes: 34

Related Questions