Random selection with criteria in python
Question: I want to (pseudo)randomly select an object from a list that fits a criterion.
I have a function that does this for one criterion I need:

    
    
    from random import randint
    def choose(array):
        return array[randint(0,len(array)-1)]
    def choose_c(array):
        result = 'r'
        while result[-1] == 'r':
            result = choose(array)
        return result
    

But each time I want a new criterion I need to write a new function. Is there
a simpler way?


Answer: One approach is to make your `choice_c` function accept a callable, which will
be evaluated on the randomly sampled result until it evaluates to `False`, at
which point the random sample will be returned.

    
    
    def choice_c(array, criterion=None):
        result = choose(array)
        if criterion:
            while criterion(result):
                result = choose(array)
    
        return result
    
    def r_criterion(some_sample):
        return some_sample == "r"
    
    def gt5_criterion(some_sample):
        return some_sample > 5
    
    choice_c(array, r_criterion)
    choice_c(array, gt5_criterion)
    

This can also be accomplished using `dropwhile` and/or `takewhile` from the
`itertools` module, and if this will be used heavily it might be worth making
the `choose` function behave as a generator to use this implementation.

    
    
    from itertools import dropwhile
    
    def choose(array):
        while True:
            yield array[randint(0,len(array)-1)]
    
    def choice_c(array, criterion=None):
        gen = choose(array)
        return next(dropwhile(criterion, gen)) if criterion else next(gen)
    

Of course, in both cases, this places the burden on you to write good unit
tests, or otherwise ensure that the criterion functions make sense on the
array contents, and that any errors are handled correctly, and that you don't
loop over an infinite generator in the `while` section ...

