Python,循环遍历字符串并就地更改特定单词开头和结尾的字符。

3

我将尝试使用符合特定格式的单词在字符串内创建一些变量。

例如,我的原始字符串是:

string = '@Cost1 + (@Cost2 + @Cost3) / @Revenue1 * 1.2'

我已经创建了以下字典:

mydict = {'Cost1' : 10, 'Cost2' : 5, 'Cost3' : 1, 'Revenue1' : 10}

我想创建一个函数,将@Cost1(例如)替换为:mydict.get('Cost1'),这样我就可以将@视为变量标记,并在我的字典中查找值。
因此,我的意图是:
  • mydict.get('替换@,这非常容易使用string.replace()函数
  • 在跟随@words的字母链的末尾添加') --> 这个我很难实现
我考虑使用for循环,但是在逻辑上难以在每个前面加上"')". 也考虑过生成器,但不太确定。
另外,我想添加一个检查,确保每个@Cost1、@Cost2等都在我的字典中,但这个我应该能做到。
谢谢!
Eric
编辑:
根据您的评论,我希望我的最终输出为:
string = mydict.get('Cost1') + ( mydict.get('Cost2') + mydict.get('Cost3') ) / mydict.get('Revenue1') * 1.2'

1
你能发布一个样本输出吗? - DirtyBit
1
我不知道 "在跟随 @words 的字母链的末尾添加 ')'" 是什么意思。什么是"跟随 @words 的字母链的末尾"? - Aran-Fey
2个回答

4
我认为你需要捕获一个正则表达式@+字母/数字/下划线,即"@(\w+)(匹配@,然后匹配一个或多个字母/数字/下划线并创建一个与它们匹配的组),并将其提供给一个替换函数
import re
mydict = {'Cost1' : 10, 'Cost2' : 5, 'Cost3' : 1, 'Revenue1' : 10}
string = '@Cost1 + (@Cost2 + @Cost3) / @Revenue1 * 1.2'

expression = re.sub("@(\w+)",lambda m : str(mydict.get(m.group(1),0)),string)

结果:

'10 + (5 + 1) / 10 * 1.2'

该方法非常高效,因为它使用字典查找而不是循环来替换和创建与变量数量相同的多个字符串。
请注意,任何未知的变量都会产生0。如果您不希望出现这种情况,请使用mydict[m.group(1)]触发键错误。 lambda也不是必须的。只要它以match对象作为输入并返回一个字符串作为输出,您就可以编写一个真正的函数:
def repfunc(m)
    return str(mydict.get(m.group(1),0))

re.sub("@(\w+)",repfunc,string)

这就是为什么在获取值后要转换成字符串的原因。
一旦您具有该表达式,您可以应用评估器(eval是最简单但不太安全的方法,ast.literal_eval无法工作,因为它不支持操作,但还有其他选项,例如第三方模块simpleeval(它可以提供一个变量列表,这将进一步简化答案),或者其他示例,请参见这里:Evaluating a mathematical expression in a string)。

谢谢Jean-François!就是这样。还有一个问题,我想正确地捕获错误: 我该怎么做?当我按照你说的添加mydict[m.group(1)]时,它会给我一个键错误,但我不知道是哪个键。我怎么能得到它?此外,是否可以详细说明一下以下内容的行为: "@(\w+)"在sub中以及lambda m:str(mydict.get(m.group(1),0))谢谢编辑:对不起,我犯了一个错误,我可以看到键错误。如果您能给我解释lambda函数,我将不胜感激。 - yeye
2
我已经添加了一个非lambda版本。 - Jean-François Fabre
你在 pd.series 中怎么做?我正试图做同样的事情(假设字符串是我的 pd.series 中的行)。我尝试使用 pd.Series.str.replace,但我无法做到。 然后我也想在第二次评估结果。 - yeye

1
string = '@Cost1 + (@Cost2 + @Cost3) / @Revenue1 * 1.2'
mydict = {'Cost1' : 10, 'Cost2' : 5, 'Cost3' : 1, 'Revenue1' : 10}
string = string.replace('@', '')
for i in mydict:
    string = string.replace(i, str(mydict[i]))

print(string)
print(eval(string))

输出:

10 + (5 + 1) / 10 * 1.2

10.72

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接