Search code examples
pythonvalueerrorsortedset

Python SortedSet ValueError when using discard


I am using SortedSet to store objects in sorted order. I keep getting ValueError object not in list even though the object is indeed in the list.

Here is a reproducible example

from sortedcontainers import SortedSet

a = SortedSet()

class example:
    def __init__(self,p, id):
        self.p = p
        self.id = id
    def __lt__(self, other):
        return self.p < other.p
 


a.add(example(5, 1))
x = example(5, 2)
a.add(x)

if x in a:
    print("found")
    a.discard(x)

In this example "found" is printed and I get ValueError: <__main__.example object at 0x7fc19ebb2400> not in list

I have been trying to figure out why this is failing for hours now and I would really appreciate any help.

Edit: Here is the complete traceback

Traceback (most recent call last):
  File "/CLD/clockwork-rl/work/Clockwork-RL/temp.py", line 18, in <module>
    a.discard(x)
  File "/home/salzayat/.local/lib/python3.7/site-packages/sortedcontainers/sortedset.py", line 422, in discard
    self._list.remove(value)
  File "/home/salzayat/.local/lib/python3.7/site-packages/sortedcontainers/sortedlist.py", line 462, in remove
    raise ValueError('{0!r} not in list'.format(value))
ValueError: <__main__.example object at 0x7f3783488400> not in list

Edit2:

I updated the code to fix the missing return and still produce the error.

I now understand that I need to add a condition for the id as well. I am not sure why this is necessary since it can detect that x is in the orderedset and found is still printed


Solution

  • Your class's methods are inconsistent. You have not implemented a full set of comparison methods, or a __hash__ method. All you have is __lt__.

    Also, the way you've implemented __lt__, as return self.p < other.p, implies that as far as your order comparisons are concerned, example(5, 1) and example(5, 2) are equal (contrary to how your inherited __eq__ behaves). If you want to be able to store two objects with equal p values in the same SortedSet, your comparison operators have to be able to distinguish the two objects.

    Because your methods are inconsistent, they report contradictory information to the SortedSet implementation. The hash- and ==-based parts of the implementation think your objects are different, but the <-based parts of the implementation think your objects are equal, and the SortedSet gets very confused.