我有一个词典列表,例如:
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} ...]
您知道有任何现有的库吗?或者你知道如何实现它吗?
我已经有了一个想法,如下所示,但我希望有一种更好的方法来解析公式。处理'()'等中的块的东西。
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)
答案 0 :(得分:1)
做这样的事情,你会更快乐。
Metrics = namedtuple('Metrics', 'country,sales,cost' )
Margin = namedtuple( 'Margin', 'country,sales,cost,margin' )
metrics = ( Metrics(**row) for row in l ) # a one-use only generator; not a sequence
margin = [
Margin( m.country, m.sales, m.cost,
margin= (m.sales-m.cost)/m.sales
)
for m in metrics ]
这很有效,因为您的公式margin= (m.sales-m.cost)/m.sales
非常,非常容易阅读,理解和修改。
答案 1 :(得分:1)
在我看来,真正的问题是将数字放在有文字的地方。
一种方法可以使用re.sub()
和一些字典格式(我真的不知道它们的真实姓名,bute 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]
匹配任何字母字符。+
后面的r'{d[\1]}'
告诉匹配一个或多个,在我们的案例中是字母字符,toghter。\1
是替代品。
{d[
代表“放在第1组”。]}
>>> '{d[first]} + {d[second]}'.format(d=dct)
'1 + 2'
匹配的内容。要了解有关re模块的更多信息,请查看official doc。
格式如何运作:
{{1}}
将这两件事放在一边strip()
,这里和那里有干净的字符串,你最终会得到上面的代码。