(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 now "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?
CodePudding user response:
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.
CodePudding user response:
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 (a := randrange(0, len(subs))) == idx:
pass
print(subs[a])
except ValueError:
pass
The try
clause tries to find the index in subs
with corresponding element equal to the word x
.
- In the event that
x
is not found, aValueError
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 forsubs
) toa
untila
is not equal toidx
. Oncea
is not equal toidx
, we break out of the loop and printsubs[a]
.
Drawing inspiration from @Mad Physicist, it would be better if the while
statement were replaced with
if (a := randrange(0, len(subs) - 1)) >= idx:
a = 1
which assigns a
to a random integer in [0, len(subs) - 1)
and compares it against idx
. In the event that a
is greater than or equal to idx
, a
is incremented by 1.
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