-1

Check this out, please tell me what I can do to make it work. I get an obvious error here stating that I cannot change the set while I'm iterating it. I think what I'm trying to do is clear here but I have struggled on this long enough and am seeking guidance.

class SetOfSets(set):
    def __init__(self,setofsets):
        """
        initialize with family of sets
        """
        set.__init__(self,list(setofsets))
    def remove(self,element):
        """
        remove all sets from set with element in it
        """
        for inset in self:
            if element in inset:
                self.remove(element)
user3659451
  • 1,913
  • 9
  • 30
  • 43
  • 5
    The code you posted will *recurse infinitely*, not throw the exception you claim it does. Show us the actual code and the *full traceback*. – Martijn Pieters Jul 24 '14 at 06:30
  • 4
    Well, not _infinitely_ ... the python recursion limiter will take over at some point ;-). (Of course, I'm just being a pain and @Martijn is completely right in the sentiment) – mgilson Jul 24 '14 at 06:35
  • 1
    @mgilson: you pedant, you. :-) – Martijn Pieters Jul 24 '14 at 06:36
  • 1
    You can't have a set of sets, because sets can only hold hashable contents and are not themselves hashable. You can have a set of frozensets, but I don't see why you need a custom class to implement that. – jonrsharpe Jul 24 '14 at 06:53
  • It looks much like *list* of sets, OP might be confusing lists and sets. – J0HN Jul 24 '14 at 07:16
  • @jonrsharpe eventually I'd like to add more functionality, so yes I'd like to make a set of frozen sets. More specifically a set of 2-tuples. – user710587 Jul 24 '14 at 07:31
  • @user710587 tuples aren't frozensets. See [the docs](https://docs.python.org/2.7/library/stdtypes.html#set-types-set-frozenset). – jonrsharpe Jul 24 '14 at 07:46
  • @jonrsharpe: So if I want to bring tuples in and out of my set class, have functionality which evaluates what is in the tuple to determine whether they stay or go, this is impossible? What's the right way to go about this? – user3659451 Jul 24 '14 at 16:36
  • No, of course it's not impossible. Read the documentation - a `tuple` is a valid `set` member and `set.discard` lets you remove members. But you can't discard while iterating over it - get a list (or set!) of tuples to be removed, then iterate over *that* and remove them. And you shouldn't call it `SetOfSets` if that's not what it is, as that will confuse other users of your code. – jonrsharpe Jul 24 '14 at 16:43
  • Thanks! discard was great. – user3659451 Jul 24 '14 at 17:23
  • @user3659451 no problem; I have updated my answer to use proper set methods, which should be more efficient. – jonrsharpe Jul 24 '14 at 18:29

2 Answers2

0

To follow up on my comment with a code sample, here is how you can remove all of the tuples containing 2 from a set, without trying to modify the set while iterating over it:

>>> s = set([(1, 2), (3, 4), (2, 3), (2, 5)])
>>> s
set([(1, 2), (2, 3), (2, 5), (3, 4)])
>>> to_remove = set(t for t in s if 2 in t)
>>> to_remove
set([(1, 2), (2, 5), (2, 3)])
>>> s.difference_update(to_remove)
>>> s
set([(3, 4)])
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
-1

Why you are having the problem and the solution is answered clearly in another post (click here for original post):

Python's complaining because the inner set objects are mutable and thus not hashable. The solution is to use frozenset for the inner sets, to indicate that you have no intention of modifying them.

That is to say, you can have a set of sets, but you can't modify inner sets. Thus, it won't achieve the goal you want.

-- That said, Python set needs to be hashable because it wants to support O(1) lookup. If that is not a requirement for your set data structure, then I would go with using list of sets to mimic set of sets. But the downside is before modification of inner sets, or before addition inside inner sets, you have to run through the whole list to check if the modification/addition will make two sets in the list to be redundant. And that takes O(M) time, where M is the number of all elements in the list. That is way too huge.

Community
  • 1
  • 1
jw2013
  • 64
  • 1
  • 1
  • 3
  • Although correct, this does not address the error that the OP is reporting. – jonrsharpe Jul 24 '14 at 07:40
  • It does. You can't even pass in sets of set to his __init__. – jw2013 Jul 24 '14 at 07:46
  • So if I want to bring tuples in and out of my set class, have functionality which evaluates what is in the tuple to determine whether they stay or go, this is impossible. This is what I am seeing from all of these posts. I find this very sad :(, maybe Python was the wrong language to try this in. – user3659451 Jul 24 '14 at 16:10