我有一个字典列表,例如:
l =[{country:'Italy',sales:100,cost:50}{country:'Italy',sales:130,cost:60}
{country:'Germany',sales:110,cost:50}]
我想要一个Python函数,它接受类似电子表格的输入字符串(请阅读下面@lott的评论)公式如下:
margin = (sales-cost)/sales
它给了我返回:
l = [{country:'Italy',sales:100,cost:50,margin:1} ...]
您知道现有的库可以做到这一点吗?或者您知道如何实现它吗?
我已经有了一个想法,如下所示,但我想要一种更好的方法来解析公式。处理“()”中的 block 或类似的东西。
parsed_op = {'sales':1,'cost':-1}
calc_field_name = 'smi'
counter = -1
for d in data:
counter = counter + 1
calc = sum([float(d[item])*parsed_op[item] for item in parsed_op])
d[calc_field_name] = calc
del data[counter]
data.append(d)
最佳答案
在我看来,真正的问题是将数字放在有文字的地方。
一种方法可以使用 re.sub()
和一些字典格式(我真的不知道他们的真实姓名,但是here有一些例子)。
代码:
import re
dct = {'country': 'Italy', 'sales': 100, 'cost': 50}
formula = 'margin = (sales-cost)/sales'
res_name,operation = formula.split('=')
num_formula = re.sub(r'([a-zA-Z]+)', r'{d[\1]}', operation.strip()).format(d=dct)
num_formula # '(100-50)/100'
dct[res_name.strip()] = eval(num_formula.format(d=dct))
结果:
{'country': 'Italy', 'cost': 50, 'margin': 0.5, 'sales': 100}
我使用eval()
来评估字符串中的数字运算。通常使用eval()
是一种不好的做法,但这里非常方便。
无论如何,我确信您可以用其他东西替换 eval()
评估。
快速说明
re.sub()
的作用:
>>> re.sub(r'([a-zA-Z]+)', r'{d[\1]}', '(sales-cost)/sales')
'({d[sales]}-{d[cost]})/{d[sales]}'
r'([a-zA-Z]+)'
是模式。[a-zA-Z]
匹配任何字母字符。- 后面的
+
告诉我们要匹配一个或多个,在我们的例子中是字母字符。 - 括号用于分组。这意味着里面的东西将是一个团体。由于我们只有一对括号,因此属于第 1 组。
r'{d[\1]}'
是替换。\1
代表“放置组号 1”。- 所以基本上会包装与
{d[
]}
匹配的内容。
要了解有关 re 模块的更多信息,请查看 official doc .
格式化的工作原理:
>>> '{d[first]} + {d[second]}'.format(d=dct)
'1 + 2'
将这两件事放在一起 strip()
到处都有干净的字符串,您将得到上面的代码。
关于Python 类似电子表格的公式解析器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9436959/