Elegant way to apply series of functions to a string based on condition

Question:

I have a function with x boolean arguments like the following:

def generic_function(input_string: str, a = True, b = True, c = True, d = True):
'''A generic function that applies a  series of action
to a string'''

if a == False and b == True and c == True and d == True:

   input_string = action_d(action_c(action_b(input_string)))

else if a == False and b == False and c == True and d == True:

   input_string = action_d(action_c((input_string))

#etc.

return input_string

I would like to avoid having to specify each condition specifically and make my code less verbose.

Is there a better, more elegant way to do this? Just to be clear: the original function is part of a class which defines and applies a series of functions to a text to extract some data. For instance, action_a is an emojis removal function, action_b is a tokenizer, etc.

Asked By: corvusMidnight

||

Answers:

One thing you can do is basically pass an iterable of all the Booleans to all builtin which will definitely make your code look cleaner as you have all the conditions combined by and, you can use any in case if boolean is combined by or , or you can combine all, any depending on the conditions you have.

def generic_function(input_string: str, a = True, b = True, c = True, d = True):
    '''A generic function that applies a  series of action
    to a string'''

    if all((not a,b,c,d,)):
       input_string = action_d(action_c(action_b(input_string)))
    elif all((not a, not b, c, d)):
       input_string = action_d(action_c((input_string))
    #etc.
    
    return input_string
Answered By: ThePyGuy

You don’t have to make every possible combination. Since the logic is to apply a function on the return of the previous one (g∘f), using a sequence of if is fine and totally equivalent.

def generic_function(input_string: str, a=True, b=True, c=True, d=True):
    if a:
        input_string = action_a(input_string)
    if b:
        input_string = action_b(input_string)
    if c:
        input_string = action_c(input_string)
    if d:
        input_string = action_d(input_string)
    return input_string
Answered By: ErnestBidouille

we could use some standart libraries and get this quite elegant (IMHO) solution:

from functools import reduce
from itertools import compress

def generic_function(input_string: str, a = True, b = True, c = True, d = True):
    funcs = compress([action_a, action_b, action_c, action_d],[a,b,c,d])
    return reduce(lambda x,y: y(x), funcs, input_string)

let’s test it:

action_a = lambda a: a+'a'
action_b = lambda b: b+'bb'
action_c = lambda c: c+'ccc'
action_d = lambda d: d+'dddd'

generic_function('test_')  # 'test_abbcccdddd'
generic_function('test_', a=False, c=False)  # 'test_bbdddd'
Answered By: SergFSM
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.