HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Faster Way of Comparing Generic Sets

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
genericcomparingwayfastersets

Problem

The following extension method is the limiting factor in the performance of an application I am developing, according to Visual Studio 2012 Performance Analysis profiler.

Is there a faster way to compare two collections for set equality?

public static bool SetEqual(this IEnumerable source, IEnumerable other, IEqualityComparer comparer = null)
{
if (source == null) {
throw new ArgumentNullException("source");
}

if (other == null) {
throw new ArgumentNullException("other");
}

ICollection sourceCollection = source as ICollection ?? source.ToArray();
ICollection otherCollection = other as ICollection ?? other.ToArray();

if (sourceCollection.Count != otherCollection.Count) {
return false;
}

if (sourceCollection.Except(otherCollection, comparer).Any()) {
return false;
}

if (otherCollection.Except(sourceCollection, comparer).Any()) {
return false;
}

return true;
}

Solution

It seems you are iterating the sets a lot with the Except method and possibly the ToArray.

Consider iterating the sets at most once:

public static bool SetEqual(this IEnumerable source, IEnumerable other, IEqualityComparer comparer = null)
{
    if (source == null)
        throw new ArgumentNullException("source");

    if (other == null)
        throw new ArgumentNullException("other");

    if (source is ICollection &&
        other is ICollection &&
        ((ICollection)source).Count != ((ICollection)other).Count)
        return false;

    HashSet set;
    if (comparer == null)
        set = new HashSet(source);
    else
        set = new HashSet(source, comparer);

    return set.SetEquals(other);
}


Source IEnumerable implementation.

Code Snippets

public static bool SetEqual<T>(this IEnumerable<T> source, IEnumerable<T> other, IEqualityComparer<T> comparer = null)
{
    if (source == null)
        throw new ArgumentNullException("source");

    if (other == null)
        throw new ArgumentNullException("other");

    if (source is ICollection &&
        other is ICollection &&
        ((ICollection)source).Count != ((ICollection)other).Count)
        return false;

    HashSet<T> set;
    if (comparer == null)
        set = new HashSet<T>(source);
    else
        set = new HashSet<T>(source, comparer);

    return set.SetEquals(other);
}

Context

StackExchange Code Review Q#68288, answer score: 5

Revisions (0)

No revisions yet.