corvusMidnight
corvusMidnight

Reputation: 648

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

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.

Upvotes: 2

Views: 94

Answers (3)

SergFSM
SergFSM

Reputation: 1491

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'

Upvotes: 1

ErnestBidouille
ErnestBidouille

Reputation: 1146

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

Upvotes: 3

ThePyGuy
ThePyGuy

Reputation: 18426

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

Upvotes: 2

Related Questions