We will
- create a new
List<T>
by passing thesource
to the constructor - iterate over
other
and remove each item ofother
from theList<T>
EachThis had been very slow, as for each call to TRemove()
we use, should implement the IEquatable<T>
interfaceList
has been iterated over. I initially did a timing which evaluated to assurebeeing the equalityfastest, but unfortunately I did my timing with an changed version of twothe test mjolka provided. It is the fastest, but only if both TIEnumerable
will contain absolutly unique items. Both for the single IEnumerable
and each item to the other IEnumerable
.
public static bool SetEqual<T>(this IEnumerable<T> source, IEnumerable<T> other, IEqualityComparer<T> comparer = null)
{
if (source == null)
{
return other == null;
}
if (other == null)
{
return false;
}
ICollection<T> sourceCollection = source as ICollection<T>;
ICollection<T> otherCollection = other as ICollection<T>;
if (sourceCollection != null && otherCollection != null)
{
if (sourceCollection.Count != otherCollection.Count)
{
return false;
}
}
IList<T> sourceList = new List<T>(source);
foreach (T item in other)
{
if (!sourceList.Remove(item)) { return false; }
}
return sourceList.Count == 0;
}
Updated timing
1000 / 1000: 00:00:00.1250604 HashSet (Timed on my computer)
1000 / 1000: 00:00:00.2211285 Original (Timed on my computer)
1000 / 1000: 00:00:00Thanks to @dmitry for pointing this out.4917692 MyDictionary (Timed on my computer)
1000 / 1000: 00:00:00 If you want to see the implementation, check the edit history.1868693 Dmitry's Dictionary (Timed on my computer)
1000 / 1000: 00:00:00.0074877 IList (Timed on my computer)
We will
- create a new
List<T>
by passing thesource
to the constructor - iterate over
other
and remove each item ofother
from theList<T>
Each T
we use, should implement the IEquatable<T>
interface to assure the equality of two T
.
public static bool SetEqual<T>(this IEnumerable<T> source, IEnumerable<T> other, IEqualityComparer<T> comparer = null)
{
if (source == null)
{
return other == null;
}
if (other == null)
{
return false;
}
ICollection<T> sourceCollection = source as ICollection<T>;
ICollection<T> otherCollection = other as ICollection<T>;
if (sourceCollection != null && otherCollection != null)
{
if (sourceCollection.Count != otherCollection.Count)
{
return false;
}
}
IList<T> sourceList = new List<T>(source);
foreach (T item in other)
{
if (!sourceList.Remove(item)) { return false; }
}
return sourceList.Count == 0;
}
Updated timing
1000 / 1000: 00:00:00.1250604 HashSet (Timed on my computer)
1000 / 1000: 00:00:00.2211285 Original (Timed on my computer)
1000 / 1000: 00:00:00.4917692 MyDictionary (Timed on my computer)
1000 / 1000: 00:00:00.1868693 Dmitry's Dictionary (Timed on my computer)
1000 / 1000: 00:00:00.0074877 IList (Timed on my computer)
This had been very slow, as for each call to Remove()
the List
has been iterated over. I initially did a timing which evaluated to beeing the fastest, but unfortunately I did my timing with an changed version of the test mjolka provided. It is the fastest, but only if both IEnumerable
will contain absolutly unique items. Both for the single IEnumerable
and each item to the other IEnumerable
.
Thanks to @dmitry for pointing this out. If you want to see the implementation, check the edit history.