简体   繁体   中英

Is there a way to "generalize" this python routine into a function

Essentially I'd like to perform a switch statement based on the existence of an item's value in a list and then perform calculations that item if it exists. Notice the difference do_calculations_on() and do_something_else_on methods.

l = ['no','maybe','yes']

item0 = next(filter(lambda x: x == 'no', l),"default")
if item0:
    print(item0) #'no'
    do_calculations_on(item0)


item_dne = next(filter(lambda x: x == 0, l), "-1")
if not item_dne:
    print(item_dne) # -1
    
item2 = next(filter(lambda x: x == 'yes', l), "dft")
if item2:
    print(item2) #'yes'
    do_something_else_on(item2)

to something that looks like (pseudocode)

if ('yes')
    then do_calculations_on('yes')
elif ('-1')
    then print('-1')
else ('no')
    then do_something_else_on('no')

EDIT: I think I have made this example more complicated than it should have been.

I am giving a list of dictionary elements that are of the form

d = {'foo': foo_value, 'bar': bar_value} .

I am given multiple d elements as a list so

[d1,d2,..] =. [{'foo': foo_value1, 'bar': bar_value1},{'foo': foo_value2, 'bar': bar_value2},...]

I want to know if this_bar_value exists in a dictionary within that list, and if it does, use the dictionary element corresponding to that value.

My attempt at doing this is to perform a "first-or-default" on the list like:

found_d = next(filter(lambda x: x['bar'] == 'this_bar_value',[d1,d2,..] ), {})`

if found_d:
    do_something_to(found_d)

But then I want to do other things when other 'bar_values' exist in a dictionary in the list and use that dictionary to perform other calculations. So essentially I want to generalize something like:

found_d1 = next(filter(lambda x: x['bar'] == 'this_bar_value',[d1,d2,..] ), {})`

if found_d1:
    do_something_to(found_d)


another_d = next(filter(lambda x: x['bar'] == 'new_bar_value',[d1,d2,..] ), {})`

if another_d:
    do_another_thing(another_d)

to something like

def new_method(bar_value, list_of_dictionariess):
    if bar_value == 'this_bar_value':
         do_something_to(found_d)  # having trouble thinking about how to compare bar_value and using its corresponding dictionary
    elif bar_value == 'another_bar_value':
         do_another_thing(another_d)

The map function below is close so, it would look like:

map(func, [d1,d2,...]) 

def func(d):
bar_value = d['bar']
    if bar_value == 'this_bar_value':
         do_something_to(found_d)  
    elif bar_value == 'another_bar_value':
         do_another_thing(another_d)

but the issue with this is that I would like to pass other parameters.i built (that are not lists) into this function, so take a look at local_var1 and local_var2.

local_var1 = 10
local_var2 = 12

map(func, [d1,d2,...]) 

def func(d):
    bar_value = d['bar']
    
    if bar_value == 'this_bar_value':
         do_something_to(d, local_var1)  
    elif bar_value == 'another_bar_value':
         do_another_thing(d, local_var2)

Still no sure what do you want, but you can wrap your pseudocode into a function and use it in map :

l = ['no','maybe','yes']

def func(x):
    if x == 'yes':
        # do something
        return 1
    elif x == 'no':
        # do something
        return 2
    else:
        # do something
        return 3

print(list(map(func, l)))
# -> [2, 3, 1]

Edit based on question update:

I believe this structure of list of dictionaries is kinda tricky. But if need to use it, and you just want to retrieve the info from your dict:

def new_method(target_value, list_of_dictionaries):
    # Subset list of dictionaries to a single dictionary matching the output
    try:
        d = [{k: v for k,v in d.items() if v == target_value} for d in list_of_dictionaries if target_value in d.values()][0]
    except:
        print(f'The target_value "{target_value}" is not in dict values.')
        return None
    # Conditionals
    if target_value == 'bar_value1':
        # do something to dict subset `d`
        return d
    elif target_value == 'bar_value2':
        # do something to dict subset `d`
        return d
    else:
        return 'default_output'

Or if you need to update the dictionary values inplace :

def new_method_inplace(target_value, list_of_dictionaries):
    # Get the list index and dict key of the target dictionary
    try:
        idx, key = [(i,k) for i,d in enumerate(list_of_dictionaries) if target_value in d.values() for k,v in d.items() if v==target_value][0]
    except:
        print(f'The target_value "{target_value}" is not in dict values.')
        return None
    # Conditionals
    if target_value == 'bar_value1':
        # do something inplace to dict subset `list_of_dictionaries[idx][key]`
        list_of_dictionaries[idx][key] = 'result_of_calculation'
    elif target_value == 'bar_value2':
        # do something inplace to dict subset `list_of_dictionaries[idx][key]`
        list_of_dictionaries[idx][key] = 'result_of_calculation'
    else:
        return 'default_output'

Examples:

list_of_dictionaries = [
    {'foo': 'foo_value1', 'bar': 'bar_value1'},
    {'foo': 'foo_value2', 'bar': 'bar_value2'}
]

new_method(target_value='bar_value2', list_of_dictionaries=list_of_dictionaries)
# -> {'bar': 'bar_value2'}

new_method(target_value='foo_value1', list_of_dictionaries=list_of_dictionaries)
# -> 'default_output'

new_method(target_value='inexistent_value', list_of_dictionaries=list_of_dictionaries)
# -> The target_value "inexistent_value" is not in dict values.

new_method_inplace(target_value='bar_value1', list_of_dictionaries=list_of_dictionaries)
list_of_dictionaries
# -> [{'foo': 'foo_value1', 'bar': 'result_of_calculation'},
# -> {'foo': 'foo_value2', 'bar': 'bar_value2'}]

not sure what is what you want, but how about this:

def myswitch(item,target1,target2,fun1,fun2,default=None,key=None):
    key_item = key(item) if key else item
    if key_item == target1:
        return fun1(item)
    elif key_item == target2:
        return fun2(item)
    else:
        return default

this is a generalized switch, that check if the key_item is equal to any of the given targets and if so, apply the corresponding given function, and key here is the same as the key argument of the sorted function.

Example usage:

>>> def do_something_to(x):
        print("doing something to",x )
        return 1

>>> def do_another_thing(x):
        print("doing another thing to",x)
        return 2

>>> list_of_dictionaries = [
    {'foo': 'foo_value1', 'bar': 'bar_value1'},
    {'foo': 'foo_value2', 'bar': 'bar_value2'},
    {'foo': 'foo_value3', 'bar': 'bar_value3'},
]
>>> [ myswitch(x,'bar_value1','bar_value2',do_something_to,do_another_thing, default=23, key=lambda y:y["bar"])
         for x in list_of_dictionaries]
doing something to {'foo': 'foo_value1', 'bar': 'bar_value1'}
doing another thing to {'foo': 'foo_value2', 'bar': 'bar_value2'}
[1, 2, 23]
>>> 

if those targets values can be used as dictionaries key, you can use a dictionary instead

>>> myswitch_dict={'bar_value1':do_something_to, 'bar_value2':do_another_thing}
>>> [ myswitch_dict.get(x["bar"],lambda y:23)(x) for x in list_of_dictionaries]
doing something to {'foo': 'foo_value1', 'bar': 'bar_value1'}
doing another thing to {'foo': 'foo_value2', 'bar': 'bar_value2'}
[1, 2, 23]
>>>     

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM