如何在某些特定字符串后查找字符? [化学代码]

时间:2019-06-06 18:45:37

标签: python regex

我正在尝试编写代码,在其中输入分子(为了方便起见,仅使用包括C,H,O,Cl和N的分子)进行输入并获得分子量。

就像我输入C2H4一样,它应该进行计算:

MW = mass_C * 2 + mass_H *4

我需要代码在数字之前加上字母,然后将其与“字符串”后面的数字相乘,直到到达末尾。

所以基本上,我如何获得数字前的字母?

PS:我是编码的新手:)因此,很高兴能看到书面代码,而不仅仅是解释理解我应该为RE使用的格式。

2 个答案:

答案 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,应该没有什么不同。