tags:

views:

95

answers:

2

Folks,

I know LINQ has a SequenceEquals method. This method makes sure each item value in each collection matches, in the same order.

What I'm looking for is a more "Equivalent" type of functionality. Just that both sequences contain the same items, not necessarily in the same order.

For example, nUnit has CollectionAssert.AreEqual() and CollectionAssert.AreEquivalent() that do what I'm explaining.

I know that I can do this either by:

  1. Ordering the lists ahead of time and using SequenceEquals
  2. Using Intersect, then seeing if the intersection is equal to the original sequence.

I'm so used to LINQ handling all my collection stuff like this that I'm officially getting lazy ;)

Thanks ahead of time!

Edit to give example of answer

var source = new[] {5, 6, 7};
source.Intersect(new[] {5, 7, 6}).Count() == source.Length;

Code came out pretty terse and readable this way, thanks to Toby for answer below!

+4  A: 

You could build a set and then use HashSet<T>.SetEquals. It's not strictly within LINQ, but it plays nicely with it :)

Of course, you could easily write your own extension method to extend this. Something like this:

public static bool SetEquals<T>(this IEnumerable<T> source, IEnumerable<T> other)
{
    HashSet<T> hashSet = new HashSet<T>(source);
    return hashSet.SetEquals(other); // Doesn't recurse! Calls HashSet.SetEquals
}

EDIT: As noted in comments, this ignores the number of times elements occur, as well as the ordering - so { 1, 2 } would be "set equal" to { 1, 2, 1, 2, 1, 1, 1 }. If that's not what you want, it'll get a little more complicated.

Jon Skeet
so 1,2 would "equal" 1,1,1,2,2,2?
spender
@spender: For *set* equality, that's correct. The set of elements in each collection is the same. It's worth highlighting though - will edit.
Jon Skeet
Jon, sometimes in methods like this, I can't decide whether to write it as you have it or to do something like `HashSet<T> hashSet = source as HashSet<T> ?? new HashSet<T>(source);` *potentially* saving the cost of constructing a new `HashSet<T>`. Do you have an opinion on that?
Dan Tao
This worked really well, code looked like this which is pretty compact: new HashSet<int>(new[] {5, 6, 7}).SetEquals(new[] {5, 7, 6})
CubanX
+5  A: 

I would create an extension method that does the intersect and then compares the counts.

Toby
You get the answer for giving me the idea to compare the counts, so it made it nice and compact, thanks! Looks like this: var source = new[] {5, 6, 7}; source.Intersect(new[] {5, 7, 6}).Count() == source.Length;
CubanX
@CubanX: Note that if the source contains any duplicates, then even `source.SetEquals(source)` will return false.
Jon Skeet
@Jon Good point, I might have to throw a distinct in there to ensure that won't happen.
CubanX