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.
2 Answers 2
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
.
-
\$\begingroup\$ This approach is still problematic because the structure contains more than just
Path
, and I only want to match on thePath
of eachPathDetails
structure, not all of its members. \$\endgroup\$Alexandru– Alexandru2015年02月09日 19:53:35 +00:00Commented Feb 9, 2015 at 19:53 -
1\$\begingroup\$ Then add an
IEqualityComparer
which only targets thePath
property. \$\endgroup\$Heslacher– Heslacher2015年02月09日 20:02:09 +00:00Commented Feb 9, 2015 at 20:02 -
\$\begingroup\$ So basically,
var deleted = new HashSet<PathDetails>(old, _pathOnlyEqualityComparer);
and (after callingExceptWith
on the other hash sets) I wouldreturn new HashSet<PathDetails>(deleted);
in order to revert to the default equality comparer forPathDetails
for this object? The performance boost is excellent, by the way. Thank you! \$\endgroup\$Alexandru– Alexandru2015年02月09日 21:02:08 +00:00Commented Feb 9, 2015 at 21:02 -
\$\begingroup\$ I also implemented my equality comparer's
Equals
method usingreturn (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\$Alexandru– Alexandru2015年02月09日 21:34:07 +00:00Commented Feb 9, 2015 at 21:34
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.