JohnDoe122
JohnDoe122

Reputation: 688

Loop over a dictionary efficiently

I have a dictionary of the form: {'p0': -1.0, 'p1': -9.73133548174993, 'p2': 0.0306594941614714, 'p3': 2.0, 'p4': 0.514879452523938} (much longer than this), and some expressions strings containing p0, p1 ... such as p0*x+p1**2+p3+1. I want to replace each instance of a parameter pi with its value in the dictionary. Is there a fast way to do this (in which I don't just use a for loop and .replace() for the string)? Thank you!

Upvotes: 1

Views: 107

Answers (6)

equation="p0*x+p1**2+p3+1"
mydict={'p0': -1.0, 'p1': -9.73133548174993, 'p2': 0.0306594941614714, 'p3': 2.0, 
'p4': 0.514879452523938}

for k,v in mydict.items():
    equation=re.sub(str(k),str(v),equation)

print(equation)    

output:

-1.0*x+-9.73133548174993**2+2.0+1

Upvotes: 0

Ashit Kumar Rai
Ashit Kumar Rai

Reputation: 1

d={'p0': -1.0, 'p1': -9.73133548174993, 'p2': 0.0306594941614714, 'p3': 2.0, 'p4': 0.514879452523938}
for k,v in d.items():
    locals()[k]=v        # or vars()[k]=v  or globals()[k]=v
#each keys in d is converted into variables whose values is corresponding d.values()
print(p0,p1,p2,p3,p4)

Upvotes: 0

RufusVS
RufusVS

Reputation: 4127

You have two good answers here (so far) using format_map. Now you just need a regex to to replace all your p# or p## or p### values with {} around them (as in {p#} in their answers):

import re
formula = "p0*x+p1**2+p33+1"
new_formula = re.sub(r"(p\d*)",r"{\1}",formula)
print (new_formula)

Upvotes: 2

tdelaney
tdelaney

Reputation: 77337

You could rewrite the equations to use a dictionary

def func(d, x):
    return d['p0']*x+d['p1']**2+d['p3']+1
    

Or you could use eval using the dict as a namespace

def p_func_eval(data, x):
    return eval('p0*x+p1**2+p3+1', None, data)
    
data = {'p0': -1.0, 'p1': -9.73133548174993, 'p2': 0.0306594941614714, 'p3': 2.0, 'p4': 0.514879452523938}

print(func(data, 33))

The second method needs to reparse the string every time so may be a bit slower than the first. You could precompile the expressions or cache them as you go. This is a bit more complicated and only makes a difference if you do it alot.

_p_func_cache = {}

def p_fun_eval(expression, data, x):
    if expression not in _p_func_cache:
        _p_func_cache[expression] = compile(expression, 'p_func', 'eval')
    return eval(_p_func_cache[expression], None, data)

Upvotes: 2

duckboycool
duckboycool

Reputation: 2455

The best way to do this would likely be with the str.format_map() method, although this will require the replaced elements to be surrounded in curly brackets, so if you have no way to make sure that your input data will have that, you're going to have to separately replace it anyway.

>>> in_str = '{p0}*x+{p1}**2+{p3}+1'
>>> vals = {'p0': -1.0, 'p1': -9.73133548174993, 'p2': 0.0306594941614714, 'p3': 2.0, 'p4': 0.514879452523938}
>>> in_str.format_map(vals)
-1.0*x+-9.73133548174993**2+2.0+1

Upvotes: 4

e_nicolai
e_nicolai

Reputation: 108

I think you can use something like format_map() to do this? If I understand correctly

# input stored in variable a. 
a = {'x':'John', 'y':'Wick'} 

# Use of format_map() function 
print("{x}'s last name is {y}".format_map(a)) 

Upvotes: 2

Related Questions