pythonrandompsychopy

Sample from list of lists until condition is met


I have a list of lists that I am randomly choosing a value from. The issue I am having now is that since the loop I wrote is using random.choice() there is the possibility that a given value won't be present, which will cause an error in downstream code. So I basically want to sample from this list of lists until the final list has at least one occurrence of each value (so at least one occurrence of 1-8).

Below is my current code and the output list for probe which doesn't include a single occurrence of 3 in this iteration, which will cause the subsequent code to fail.

Some restrictions I have:

  1. The final list probe needs to be only 16 items.
  2. One of the two values needs to be picked at each index because it codes for a later stimulus. So for example, probe[0] in this case needs to be either 7 or 6 and probe[15] needs to be either 3 or 2. But still with the condition that across all indexes, 1-8 appears at least once.
probe_list = [['7', '6'], ['5', '8'], ['3', '2'], ['1', '4'], ['7', '6'], ['1', '4'], ['5', '8'], ['7', '6'], ['1', '4'], ['3', '2'], ['7', '6'], ['1', '4'], ['7', '6'], ['1', '4'], ['5', '8'], ['3', '2']]
probe=[]
for i in range(len(probe_list)):
    choose = random.choice(probe_list[i])
    probe.append(choose)
probe = ['7', '8', '2', '1', '6', '1', '5', '6', '4', '2', '7', '4', '6', '4', '8', '2']

Solution

  • You could create a set, which contains all values which are already in the probe in the current "run". Then you could always check, whether the size of the set is 8. If you begin a new "run", then you have to clear() the set and the probe.

    import random 
    
    probe_list = [['7', '6'], ['5', '8'], ['3', '2'], ['1', '4'], ['7', '6'], ['1', '4'], ['5', '8'], ['7', '6'], ['1', '4'], ['3', '2'], ['7', '6'], ['1', '4'], ['7', '6'], ['1', '4'], ['5', '8'], ['3', '2']]
    
    probe=[]
    
    while True:
       contained=set()
       probe = []
       for i in range(len(probe_list)):
            choose = random.choice(probe_list[i])
            contained.add(choose)
            probe.append(choose)
       if len(contained) == 8:
            break
    
    print(probe, len(probe), len(set(probe)))
    

    It would alway ensure, that the length of the probe is 16 and the number of unique items in the probe is 8. For example the output:

    ['7', '5', '2', '4', '6', '1', '8', '7', '1', '3', '6', '4', '6', '1', '5', '3'] 16 8