我正在尝试编写代码,在其中输入分子(为了方便起见,仅使用包括C,H,O,Cl和N的分子)进行输入并获得分子量。
就像我输入C2H4
一样,它应该进行计算:
MW = mass_C * 2 + mass_H *4
我需要代码在数字之前加上字母,然后将其与“字符串”后面的数字相乘,直到到达末尾。
所以基本上,我如何获得数字前的字母?
PS:我是编码的新手:)因此,很高兴能看到书面代码,而不仅仅是解释理解我应该为RE使用的格式。
答案 0 :(得分:2)
以下是满足您需要的一些简单代码:
import re
atomic_weights = {
'Cl': 35.446,
'C': 12.0096,
'O': 15.99903,
'H': 1.00784,
}
pattern = r"(?P<element>" + "|".join(atomic_weights.keys()) + ")(?P<count>\d*)"
expression = re.compile(pattern)
while True:
formula = input("formula: ")
weight = 0
for match in expression.finditer(formula):
element = match.group('element')
count = match.group('count')
if count.isdigit():
count = int(count)
else:
count = 1
weight += atomic_weights[element] * count
print(f"{formula} weighs {weight}")
我将只关注正则表达式的使用:
|
匹配之前或之后的所有内容\d
与所有数字匹配*
,它匹配零个或多个(我们不一定需要一个数字)(?P<name>)
命名匹配的任何内容,以便以后可以轻松地再次引用然后,将公式与创建的正则表达式进行匹配,并在所有匹配项上循环查找相应的元素权重和乘数。
小笔记:此方法将完全忽略它不知道其权重的元素。那可能不是你想要的...
希望这会有所帮助!
答案 1 :(得分:0)
我不确定我的原子量是否正确,但是我想那可以解决。
对我来说,棘手的一点是试图找出类似CH3的情况,其中简单的(字母)(数字)正则表达式不起作用。
re.findall在这里做了繁重的工作。可能有更好的方法来解析C2H4字符串,对此我会很感兴趣,但这是可行的。显然,您可以清理并进行更整洁的功能等。
但是我怀疑您最感兴趣的正则表达式说:查找一串字母,大写或小写字母,然后是一串数字。这将传递给calc_weight,它将字符串分为字母和数字。这些字母将发送到原子量(如果有)。如果不是,则引发错误。然后将权重乘以数字。
import re
import sys
weight = { 'cl': 30, 'n': 8, 'o': 12, 'c': 6, 'h': 2 }
def calc_weight(my_str):
elt = my_str[1].lower()
if not re.search("[0-9]", my_str[0]): amt = 1
else: amt = re.sub("^[a-zA-Z]+", "", my_str[0])
if elt not in weight: sys.exit(elt + " is not a valid element.")
return int(amt) * weight[elt]
my_string = "C2H4"
a = re.findall("((Cl|H|O|C|N)[0-9]*)", my_string)
my_weight = 0
for b in a:
my_weight += calc_weight(b)
print("Weight of", my_string, "is", my_weight)
代码中的一个单词:my_str [0]和my_str [1]是findall的元组的一部分,因为我有两对括号。第一个是整体字符串,第二个是元素。
希望这会有所帮助。请注意,您可能可以改进代码:针对错误的字符串等抛出更好的错误消息。但是我想至少允许使用大写形式,例如如果有人输入了Mg或MG,应该没有什么不同。