# Python - If element is in list, return another unique element

(This is Python 2.7.10)

I am traversing through a list of sublists that like this:

``````for x in words:
for subs in bigLsts:
if x in subs:
print() # Here, I want to print a different word in subs that is not the same word
``````

`bigLsts` is a list of word lists formatted like this:

``````bigLsts = [
["herro", "hewwo", "holas"],
["woah", "woahwa", "whatda"]
]
``````

If `x` is in the `subs`, how can I print another word in the sublist that is not the same word as `x`? So, if `x == "hewwo"` how can I print either `"herro"` or `"holas"` but not `"hewwo"`

I have some solutions like generating a random number that does not include the index of that element, but solutions like that feel a bit clunky to me. Is there any cleaner solution?

In your inner loop, you can consider using the following `try` statement (to replace the `if x in subs`):

``````from random import randrange
try:
idx = subs.index(x)
while True:
a = randrange(0, len(subs))
if a != idx:
break
print(subs[a])
except ValueError:
pass
``````

The `try` suite tries to find the index in `subs` with corresponding element equal to the word `x`.

• In the event that `x` is not found, a `ValueError` is raised and we quietly ignore it.
• In the event that `x` is found, `idx` is assigned the corresponding index. Then, we assign a random integer in `[0, len(subs) - 1]` (i.e. the set of valid indices for `subs`) to `a` until `a` is not equal to `idx`. Once `a` is not equal to `idx`, we break out of the loop and print `subs[a]`.

Drawing inspiration from @Mad Physicist, it would be better if the `try` suite were replaced with

``````a = randrange(0, len(subs) - 1)
a += a >= subs.index(x)
``````

which assigns `a` to a random integer in `[0, len(subs) - 1)` and then increments `a` by 1 if `a >= idx` is true; otherwise (i.e. if `a < idx` is true), `a` is unchanged. If this change is made, the `try` statement becomes

``````try:
a = randrange(0, len(subs) - 1)
a += a >= subs.index(x)
print(subs[a])
except ValueError:
pass
``````

A slight optimization would be to simply catch all exceptions with `except:` (replacing `except ValueError:`). See, for example, this answer. The gist of it is that if an except clause has an expression (here, `ValueError`), it needs to be evaluated and tested against the raised exception from the `try` suite. An expression-less except clause (as in `except:`) does not have to do this additional step. I would not recommend making catching all exceptions a habit, however -- it is context-specific.

Example Session

Suppose that

``````words = ["green", "eggs", "and", "ham", "hewwo", "woahwa"]
bigLsts = [['herro', 'hewwo', 'holas'], ['woah', 'woahwa', 'whatda']]
``````

A session might yield output

``````herro
whatda
``````

Generating a random number that is not the index of the element does not have to be clunky. One simple way to do it is to generate a number that is in the range `[0, len(subs) - 2]` and add one if the number is greater than or equal to the index you want to avoid. You can use the fact that python booleans are a subtype of integers to make the computation very simple:

``````ind = random.randrange(0, len(subs) - 1)
ind += ind >= subs.index(x)
print(subs[ind])
``````

That being said, you can use an even simpler formulation, courtesy of this unrelated answer:

``````min((i for i in subs if i != x), key=lambda x: random.random())
``````

The idea is to take the element with the minimum uniformly randomly generated key. The generator automatically handles skipping the element you want to skip without doing an `index` lookup or ever mentioning indices at all.