3

I need a function, that takes two arguments a (an integer) and b (either an integer or a list of integer), to return True if a == b or a in b.

This can be easily done by putting a simple or between the two conditions, but I wanted to know if it was possible to do it in a single condition.

I thought of doing:

  • a in list(b) but it is not working because integers are not iterable,
  • a in [b] but it is not working if b is already a list.
  • The two conditions are for different criteria. You *should* be separating them with an `or`. – h0r53 May 27 '21 at 14:58
  • 1
    But, `a == b or a in b` ***is*** a single condition... – Tomerikoo May 27 '21 at 15:00
  • Well, I do not see why putting it all inside a single condition (I mean, **without logical operators**) would be the best idea, but this should work: `str(a) in str(b).replace('[', '').replace(']', '').split(', ')` – Sherlock Bourne May 27 '21 at 15:03

4 Answers4

3

Ask for forgiveness - not permission! Let's assume b is a list, and if it's not then it must be an int:

def foo(a, b):
    try:
        return a in b
    except TypeError:
        return a == b

If you insist on doing it with one expression/condition, we can actually use regular expressions here:

import re

def foo(a, b):
    return bool(re.search(rf"\b{a}\b", str(b)))

A different approach would be to change the signature of the function to take a variable amount of variables and instead of passing it a list, it should be unpacked:

def foo(a, *b):
    return a in b

And to call it:

>>> foo(4, 4)
True
>>> foo(4, *[4, 5])
True
>>> foo(4, *[5, 3])
False
>>> foo(4, 3)
False
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
  • In my opinion, '**should**' is a bit too hard. We have some built-in functions like `isinstance` for cases like this one! – Sherlock Bourne May 27 '21 at 15:17
  • 1
    @SherlockBourne Agree. Edited – Tomerikoo May 27 '21 at 15:20
  • 1
    @SherlockBourne Anyway the two can live together. We need `isinstance` for certain things. *"Ask for forgiveness - not permission"* means that instead of checking the type and then working according to it, simply guess the type and when it doesn't work fallback to something else – Tomerikoo May 27 '21 at 15:23
2

You can do return a == b if isistance(b, int) else a in b, it's a one-liner and no or/and used.

However I would go for a more readable version : return a == b or (isinstance(b, list) and a in b)

Parenthesis allow you to split your conditions in two distincts parts. If b is not a list the second part of the second condition will not be evaluated.

However to me it would be much cleaner if b was always a list even if it contains only one element.

May.D
  • 1,832
  • 1
  • 18
  • 34
2

The best solution is to use logical operators. Any other solution not involving logical operators for this specific case would be totally inefficient comparing the simplest solution.

This being said, the recommended option is the following one:

a == b or (isinstance(b, list) and a in b)

However, if for some reason you want to know how you could do it without logical operators, I have this crazy and totally not recommended option:

str(a) in str(b).replace('[', '').replace(']', '').split(', ')
Sherlock Bourne
  • 490
  • 1
  • 5
  • 10
0

I think that the best way is to work with bitwise operator & To do so you need to convert both arguments (a, b) to set().

I didn't find another way to convert b to set() without knowing it's type. so I recommend:

new_b = set(b) if isinstance(b, list) else {b}
return a in ({a} & (new_b))