0

I have a set of tuples of length 2. Tuples in set could be in format (x,y) or reversed (y,x). It's guaranteed that there exist one tuple (x,y) or (y,x) in the set, but I can't know in advance in what order.

I need to remove either (x,y) or (y,x) from the set, without knowing which it is.

I tried it like this:

def flexRemove(S, tup):
    try:
        S.remove(tup)
    except:
        S.remove(tuple([tup[1], tup[0]]))

S = {(6, 1), (2, 4), (3, 8), (7, 5)}
flexRemove(S, (4, 2))

The above example removes (4,2) or (2,4) from the set, as desired.

Is there more elegant or more pythonic way to achieve this (without invoking the Exception)?

Tibebes. M
  • 6,940
  • 5
  • 15
  • 36
Lovro
  • 185
  • 1
  • 3
  • 12
  • 1
    Python style is [Easier to ask for forgiveness than permission](https://docs.python.org/3.4/glossary.html#term-eafp). Using Exception is pythonic. You should not catch all Exception though, only the one that interest you. (`KeyError` in that case) – Lescurel Oct 07 '20 at 07:43
  • The only thing I would mention is that you avoid try/except syntax when not absolutely necessary. In your case you can replace `try` with `if tup in S` and `except` with `else`. The rest is pythonic enough. – kuco 23 Oct 07 '20 at 07:45
  • @kuco23 I disagree. Exception are more pythonic than [Look before you leap](https://docs.python.org/3.4/glossary.html#term-lbyl) – Lescurel Oct 07 '20 at 07:47
  • 1
    @Lescurel I see the issue being with multithreading. Though in this case I would prefer readability. Anyway, OP should at least specify the exception type. – kuco 23 Oct 07 '20 at 07:55

1 Answers1

2

You could use an if ... else statement instead of the try ... except block.
Quoting this answer Using try vs if in python

So, whereas an if statement always costs you, it's nearly free to set up a try/except block. But when an Exception actually occurs, the cost is much higher.

Therefore if your code raises an exception too often, then the try...except syntax is less performant. Also I find the syntax below more readable, but this is more a matter of preference, if you will.

def flexRemove(S, tup):
    if tup in S:
        S.remove(tup)
    else:
        S.remove(tuple([tup[1], tup[0]]))

S = {(6, 1), (2, 4), (3, 8), (7, 5)}
flexRemove(S, (4, 2))
print(S)

You can also write this an one-liner, like below:

def flexRemove(S, tup):
    S.remove(tup) if tup in S else S.remove(tuple([tup[1], tup[0]]))

Output:

{(6, 1), (7, 5), (3, 8)}
solid.py
  • 2,782
  • 5
  • 23
  • 30
  • Python style is [Easier to ask for forgiveness than permission](https://docs.python.org/3.4/glossary.html#term-eafp). I would argue that if we are talking about "pythonic" code, exceptions are better than a if statement. You also don't need to search twice in the list (trivial optimisation). – Lescurel Oct 07 '20 at 07:51
  • 2
    Since in my situation the probability that exception occur is ~50%, I accepted your arguments that `if..else` approach is best. – Lovro Oct 07 '20 at 08:25