tags:

views:

461

answers:

4

hi,

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 comparision should take place only if both arrays have same size

+13  A: 
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
Kyle Rozendo
but i don't think that performance is ok. intersection is not cheap operation
Andrey
@Andrey - It depends on the size of the list as well.
Kyle Rozendo
ZombieSheep
@Zombie - Good point, edited.
Kyle Rozendo
@Kyle Rozendo: your tests convinced me :)
Andrey
@Kyle Rozendo: But wait, is this meeting the OP's requirements? It hasn't been stated explicitly, but I would've assumed the OP is looking for a method to check whether the given arrays have the same elements *in the same order*. Checking `a.Intersect(b).Count()` is only going to ensure they have the same elements, without checking the order.
Dan Tao
@Kyle Rozendo: Never mind, I just noticed the OP's comment where he said they don't have to be in the same order. I'm sold ;)
Dan Tao
However wont this method fail for cases where there are duplicate elements(in both arrays).The intersect operation being a set operation may only retain distinct elements.So if you compare it with Array.length the comparison may fail.
josephj1989
@joseph - Correct. This will fail where the arrays are identical with duplicates, but there was no request for duplicate control from the OP.
Kyle Rozendo
+5  A: 

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);
Jeremy Roberts
What do you mean, "it is order independant" ? SequenceEqual is NOT order independant. In your second code sample, it will return false
Thomas Levesque
You are correct. Edited.
Jeremy Roberts
Not downvoting, but this doesn't answer the question. As per the op: `not in same order... but two arrays should have equal size`
Kyle Rozendo
+1  A: 

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" };
    
Handcraftsman
If you compare their sizes first would you need to both containsAll operation?
Scott Chamberlain
@Scott, Yes. Consider a = { "a", "b", "c" }; b = { "c", "a". "a" }; same length but the unique items in b are a subset of those in a
Handcraftsman
+3  A: 

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.

nikie