6
\$\begingroup\$

I have the following method:

public static HashSet<PathDetails> GetDeletedPaths(HashSet<PathDetails> old, HashSet<PathDetails> current)
{
 var deleted = new HashSet<PathDetails>(old);
 deleted.RemoveWhere(x => current.Any(y => y.Path == x.Path));
 return deleted;
}

PathDetails is a struct that, among other things, contains Path of type String. This method takes the longest in my application and I was wondering if there were any good ways of improving its performance. These hash sets are used elsewhere in a more hashset-friendly way, so the method must take in two sets and return a set.

asked Feb 9, 2015 at 16:06
\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

Instead of using the RemoveWhere() method together with the Any() method you should consider to just use ExceptWith() method.

public static HashSet<PathDetails> GetDeletedPaths(HashSet<PathDetails> old, HashSet<PathDetails> current)
{
 var deleted = new HashSet<PathDetails>(old);
 deleted.ExceptWith(current);
 return deleted;
}

Your approach calls for each item in deleted the Any() of current whereas ExceptWith() just calls for each item in current the Remove() method of deleted.

answered Feb 9, 2015 at 16:43
\$\endgroup\$
4
  • \$\begingroup\$ This approach is still problematic because the structure contains more than just Path, and I only want to match on the Path of each PathDetails structure, not all of its members. \$\endgroup\$ Commented Feb 9, 2015 at 19:53
  • 1
    \$\begingroup\$ Then add an IEqualityComparer which only targets the Path property. \$\endgroup\$ Commented Feb 9, 2015 at 20:02
  • \$\begingroup\$ So basically, var deleted = new HashSet<PathDetails>(old, _pathOnlyEqualityComparer); and (after calling ExceptWith on the other hash sets) I would return new HashSet<PathDetails>(deleted); in order to revert to the default equality comparer for PathDetails for this object? The performance boost is excellent, by the way. Thank you! \$\endgroup\$ Commented Feb 9, 2015 at 21:02
  • \$\begingroup\$ I also implemented my equality comparer's Equals method using return (x.Path.Equals(y.Path, StringComparison.OrdinalIgnoreCase)); in case anyone is interested, as ordinal is what I care about and it is much more performant in O(1) time. \$\endgroup\$ Commented Feb 9, 2015 at 21:34
1
\$\begingroup\$

I would recommend making a set containing the paths in current. Then instead of adding and removing PathDetails, just add them instead.

var paths = new HashSet<string>(current.Select(x => x.Path));
return new HashSet<PathDetails>(old.Where(x => !paths.Contains(x.Path)));

Since PathDetails is a struct, make sure you're overriding Equals and GetHashCode, as it can lead to improved performance.

answered Feb 9, 2015 at 20:55
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.