Results 1 to 12 of 12

Thread: [RESOLVED] Set Equals, does it exist?

  1. #1

    Thread Starter
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Resolved [RESOLVED] Set Equals, does it exist?

    I seem to occasionally find myself trying to compare two List(of T) to see whether or not they contain the same elements. A quick check of the documentation shows the SequenceEquals method, but that appears to check whether the two lists have the same length, and have the same elements in the same order. I don't care about the order. I want to know whether two collections have the same elements. Doing this is not terribly difficult, and seems common enough, so I was expecting that there would be some function that handles it. I'm not seeing one, though. Does such a thing exist?
    My usual boring signature: Nothing

  2. #2
    Fanatic Member Megalith's Avatar
    Join Date
    Oct 2006
    Location
    Secret location in the UK
    Posts
    879

    Re: Set Equals, does it exist?

    hmm not seen it, course you could sort both lists and compare that way but your not saving anything and are consuming more momory
    If debugging is the process of removing bugs, then programming must be the process of putting them in.

  3. #3
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Set Equals, does it exist?

    Quote Originally Posted by Shaggy Hiker View Post
    I was expecting that there would be some function that handles it. I'm not seeing one, though. Does such a thing exist?
    It does now. I just made one:
    Code:
    Public Function ElementsEqual(Set1 As IEnumerable(Of Object), Set2 As IEnumerable(Of Object)) As Boolean
    	Return (Set1.Count = Set2.Count) AndAlso Set1.All(Function(t) Set2.Contains(t))
    End Function

    Any good? BB

  4. #4

    Thread Starter
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Re: Set Equals, does it exist?

    Yeah, it's almost there, but I have one already built that does the same thing for the specific case that I am currently dealing with. What would be good would be a general extension. There should be two improvements on that. The first, as you mentioned, would be that there should be a quick check for the situation where the length isn't the same between the two, as that would be a fast comparison, and it is essential or else you are just looking at whether one set is a subset of the other.

    The other improvement is that it should be (Of T) rather than using objects. After all, as written, Contains seems likely to work ok as long as your objects are actually value types. It seems like there would be boxing and unboxing going on in that case, too, but I'm not sufficiently familiar with that part. For reference types, Contains might not be all that good. Now that I think about it, I'm not so sure what would happen. By default, it should just be seeing whether a certain object is in both lists. However, if you had implemented something like IEquatable for the objects in the list, does Contains look for an equal object or only the same object? Not sure.

    In any case, it seems like a generic would make sense. I might get around to that, but for now I posted this question then immediately wandered down another path, so if somebody else implements a complete solution....I might not even get to use it.
    My usual boring signature: Nothing

  5. #5
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Set Equals, does it exist?

    Ok, FWIW here's a generic extension method based on the same function. And Contains does work for reference types.

    Code:
    Public Module CollectionExtensions
       <System.Runtime.CompilerServices.Extension()> _
       Public Function ElementsEqual(Of T)(Set1 As IEnumerable(Of T), set2 As IEnumerable(Of T)) As Boolean
          Return (Set1.Count = set2.Count) AndAlso Set1.All(Function(E) set2.Contains(E))
       End Function
    End Module
    Here's a test:
    Code:
    Dim Set1 As New List(Of Control)({Button1, Button2})
    Dim Set2 As New List(Of Control)({Button2, Button1})
    Console.WriteLine(ElementsEqual(Of Control)(Set1, Set2)) 'returns True
    Set2(0) = Button1
    Console.WriteLine(ElementsEqual(Of Control)(Set1, Set2)) 'returns False

    EDIT: It doesn't seem to work as an extension method after all. But you can call it as a non-extension Generic function as in my test above.

    BB

  6. #6
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: Set Equals, does it exist?

    You could sort the two lists first and then use SequenceEqual.

  7. #7

    Thread Starter
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Re: Set Equals, does it exist?

    Yes, you could sort first, but I would expect that it would decrease performance.
    My usual boring signature: Nothing

  8. #8
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: Set Equals, does it exist?

    Perhaps, perhaps not.

    After all, this:
    Code:
    Set1.All(Function(t) Set2.Contains(t))
    enumerates Set2 for every item in Set1.

  9. #9
    PowerPoster i00's Avatar
    Join Date
    Mar 2002
    Location
    1/2 way accross the galaxy.. and then some
    Posts
    2,390

    Re: Set Equals, does it exist?

    Quote Originally Posted by boops boops View Post
    It does now. I just made one:
    Code:
    Public Function ElementsEqual(Set1 As IEnumerable(Of Object), Set2 As IEnumerable(Of Object)) As Boolean
    	Return (Set1.Count = Set2.Count) AndAlso Set1.All(Function(t) Set2.Contains(t))
    End Function

    Any good? BB
    Don't think this would be accurate.. if set1 has 100 of the same item and set two has just one occurance of the same item and 99 other items this would give a false positive match?

    Kris

  10. #10
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Set Equals, does it exist?

    Quote Originally Posted by i00 View Post
    Don't think this would be accurate.. if set1 has 100 of the same item and set two has just one occurance of the same item and 99 other items this would give a false positive match?
    Kris
    That's a good point. A mathematical Set is a collection of distinct objects, so I assumed unique items in each set. The function checks if at least one of each item in Set1 occurs in Set2.

    If the collections contain repeat items but the repeats don't matter then:
    1. there is no point in comparing the counts.
    2. it is necessary to check the reverse as well: does each item in Set2 also occur in Set1.

    If the number of repeat occurrences matters it is a different problem: comparing sorted lists is clearly the way to go. BB

  11. #11
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Set Equals, does it exist?

    Hold the press! After editing my previous post several times, it came back to me: I suggest you look at the SortedSet(T) class. You can initialize it from any IEnumerable collection, and it has a SetEquals method (as well as Intersects, IsSubsetOf, Is SupersetOf and much else). I stumbled across SortedSet in msdn a few weeks ago, and it was at the back of my mind when I first replied but I couldn't remember what it was called.

    By the way, if the items in the collection don't have to be unique, you might find the HashSet(T).SetEquals method useful.

    p.s. I just searched msdn for SetEquals. Why didn't anyone think of that?
    BB

  12. #12

    Thread Starter
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Re: Set Equals, does it exist?

    Quote Originally Posted by boops boops View Post
    Hold the press! After editing my previous post several times, it came back to me: I suggest you look at the SortedSet(T) class. You can initialize it from any IEnumerable collection, and it has a SetEquals method (as well as Intersects, IsSubsetOf, Is SupersetOf and much else). I stumbled across SortedSet in msdn a few weeks ago, and it was at the back of my mind when I first replied but I couldn't remember what it was called.
    That's a good find. I was trying to avoid the sorted set, so I didn't bother looking at SortedSet. There isn't a fundamental reason to avoid the sorted set other than a kind of esoteric one: The program that uses this has certain tasks that have to be as fast as I can make them for no other reason than that I am going to lard them up with an unknown amount of overhead. Therefore, I only wanted to sort as a last resort rather than as a matter of course. I recognized that this problem becomes considerably easier when both lists are sorted; I just thought that it would probably exist anyways. However, I think that i00 got the right of it. Instead of this being a simple, general, function, it really isn't UNLESS the sets are sorted or unique. Since uniqueness is not required for a List, only sorting makes the problem manageable.

    There is a further issue with reference types. Consider this trivial example:
    Code:
    Public Class Foo
     Public Value As Integer = 5
    End Class
    
    Dim A As New Foo
    Dim B As New Foo
    Dim myList as New List(of T)
    
    myList.Add(A)
    
    If myList.Contains(B) Then 'This will be False
    The final line evaluates to False, as it should, since B is not in the collection. However, a more practical example, which would take too long to set up, would expect this line to return True. A person might reasonable be wanting to know whether List1 contains elements that equal the elements in List2. The question is not whether myList contains the actual object, but whether myList contains an object that would be equal to the object. When I was looking (in the wrong place) yesterday, I found that many of the aggregates that worked with set intersections included an overload that had a comparison function. I figured that was so that people could supply a custom comparator. I think the same should be available for this....except that, as noted previously, the whole thing only works well for unique or sorted sets.

    p.s. I just searched msdn for SetEquals. Why didn't anyone think of that?
    BB
    There is always a problem with searches: If you have your mind fixed on the solution appearing in one guise, and that fixation is wrong, you will not find what you don't know to be looking for.


    This has been an excellent discussion. My thanks to all of you.
    My usual boring signature: Nothing

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width