使用子公式修复数据解析和计算摩尔质量

问题描述 投票:0回答:2

我正在制作一个可以考虑子公式的化合物的摩尔质量计算器。

例如:

  • “H20”应该输出~18.01528
  • “C3H5(OH)3”应该输出~92.09

这是代码:

import re
atomic_mass = { "H": 1.00797,"He": 4.00260,"Li": 6.941,"Be": 9.01218,"B": 10.81,"C": 12.011,"N": 14.0067,"O": 15.9994,"F": 18.998403,"Ne": 20.179,"Na": 22.98977,"Mg": 24.305,"Al": 26.98154,"Si": 28.0855,"P": 30.97376,"S": 32.06,"Cl": 35.453,"K": 39.0983,"Ar": 39.948,"Ca": 40.08,"Sc": 44.9559,"Ti": 47.90,"V": 50.9415,"Cr": 51.996,"Mn": 54.9380,"Fe": 55.847,"Ni": 58.70,"Co": 58.9332,"Cu": 63.546,"Zn": 65.38,"Ga": 69.72,"Ge": 72.59,"As": 74.9216,"Se": 78.96,"Br": 79.904,"Kr": 83.80,"Rb": 85.4678,"Sr": 87.62,"Y": 88.9059,"Zr": 91.22,"Nb": 92.9064,"Mo": 95.94,"Tc": 98,"Ru": 101.07,"Rh": 102.9055,"Pd": 106.4,"Ag": 107.868,"Cd": 112.41,"In": 114.82,"Sn": 118.69,"Sb": 121.75,"I": 126.9045,"Te": 127.60,"Xe": 131.30,"Cs": 132.9054,"Ba": 137.33,"La": 138.9055,"Ce": 140.12,"Pr": 140.9077,"Nd": 144.24,"Pm": 145,"Sm": 150.4,"Eu": 151.96,"Gd": 157.25,"Tb": 158.9254,"Dy": 162.50,"Ho": 164.9304,"Er": 167.26,"Tm": 168.9342,"Yb": 173.04,"Lu": 174.967,"Hf": 178.49,"Ta": 180.9479,"W": 183.85,"Re": 186.207,"Os": 190.2,"Ir": 192.22,"Pt": 195.09,"Au": 196.9665,"Hg": 200.59,"Tl": 204.37,"Pb": 207.2,"Bi": 208.9804,"Po": 209,"At": 210,"Rn": 222,"Fr": 223,"Ra": 226.0254,"Ac": 227.0278,"Pa": 231.0359,"Th": 232.0381,"Np": 237.0482,"U": 238.029,"Pu": 242,"Am": 243,"Bk": 247,"Cm": 247,"No": 250,"Cf": 251,"Es": 252,"Hs": 255,"Mt": 256,"Fm": 257,"Md": 258,"Lr": 260,"Rf": 261,"Bh": 262,"Db": 262,"Sg": 263,"Uun": 269,"Uuu": 272,"Uub": 277 }

def separate_string_number(string):
    previous_character = string[0]
    groups = []
    newword = string[0]
    for x, i in enumerate(string[1:]):
        if i.isalpha() and previous_character.isalpha():
            newword += i
        elif i.isnumeric() and previous_character.isnumeric():
            newword += i
        else:
            groups.append(newword)
            newword = i

        previous_character = i

        if x == len(string) - 2:
            groups.append(newword)
            newword = ''
    return groups



def separate_glued_elements(list):
    temp = []
    for item in list:
        if item.isalpha():
            temp.append(re.findall('[A-Z][^A-Z]*', item))
        else:
            temp.append(item)
    return [item for row in temp for item in row]


testformula = 'H20HeO(CO2)3'
print(separate_glued_elements(separate_string_number(testformula)))

到目前为止,我已经构建了一个系统,该系统基本上可以正确地将字符串输入拆分为元素数组并按顺序出现,

输入/输出示例:

流程: userIn ->separate_string_number ->separate_glued_elements ->尚未开始计算功能

用户输入 (<-): H20eO(CO2)3

separate_string_number (->): ['H', '20', 'HeO', '(', 'CO', '2', ')', '3']

seperate_glued_elements (->): ['H', '2', '0', 'He', 'O', '(', 'C', 'O', '2', ')', '3 ']

EX: H20HeO(CO2)3 的形式为 ['H', '2', '0', 'He', 'O', '(', 'C', 'O', '2', ')', '3'];

这是一个问题,它不是解析为 ['H', '20', 'He'...] 而是拆分为 ['H', '2', '0', 'He'.. .]

最重要的是,我一生都无法弄清楚一旦获得数据后如何实际使用它。

python parsing user-input calculator chemistry
2个回答
0
投票

我通过更改粘合元素功能来修复它。在旧代码中,数字仍然是字符串,并且单独的字符串函数通过拆分所有字符串来工作,所以现在 20 不再是字符串

def seperate_glued_elements(chem_list):
temp1 = []
for item in chem_list:
    if item.isnumeric():
        temp1.append(int(item))
    else:
        temp1.append(item)
temp2 = []
for item in temp1:
    if type(item) == str:
        if item.isalpha():
            temp3 = re.findall('[A-Z][^A-Z]*', item)
            for subitem in temp3:
                temp2.append(subitem)
        else:
            temp2.append(item)
    else:
        temp2.append(item)
return temp2

0
投票

这是已完成的项目代码,供将来需要的任何人使用。 (我知道这不是很好,但它确实有效)

import re

atomic_mass = { "H": 1.00784,"He": 4.00260,"Li": 6.941,"Be": 9.01218,"B": 10.81,"C": 12.011,"N": 14.0067,"O": 15.9994,"F": 18.998403,"Ne": 20.179,"Na": 22.98977,"Mg": 24.305,"Al": 26.98154,"Si": 28.0855,"P": 30.97376,"S": 32.06,"Cl": 35.453,"K": 39.0983,"Ar": 39.948,"Ca": 40.08,"Sc": 44.9559,"Ti": 47.90,"V": 50.9415,"Cr": 51.996,"Mn": 54.9380,"Fe": 55.847,"Ni": 58.70,"Co": 58.9332,"Cu": 63.546,"Zn": 65.38,"Ga": 69.72,"Ge": 72.59,"As": 74.9216,"Se": 78.96,"Br": 79.904,"Kr": 83.80,"Rb": 85.4678,"Sr": 87.62,"Y": 88.9059,"Zr": 91.22,"Nb": 92.9064,"Mo": 95.94,"Tc": 98,"Ru": 101.07,"Rh": 102.9055,"Pd": 106.4,"Ag": 107.868,"Cd": 112.41,"In": 114.82,"Sn": 118.69,"Sb": 121.75,"I": 126.9045,"Te": 127.60,"Xe": 131.30,"Cs": 132.9054,"Ba": 137.33,"La": 138.9055,"Ce": 140.12,"Pr": 140.9077,"Nd": 144.24,"Pm": 145,"Sm": 150.4,"Eu": 151.96,"Gd": 157.25,"Tb": 158.9254,"Dy": 162.50,"Ho": 164.9304,"Er": 167.26,"Tm": 168.9342,"Yb": 173.04,"Lu": 174.967,"Hf": 178.49,"Ta": 180.9479,"W": 183.85,"Re": 186.207,"Os": 190.2,"Ir": 192.22,"Pt": 195.09,"Au": 196.9665,"Hg": 200.59,"Tl": 204.37,"Pb": 207.2,"Bi": 208.9804,"Po": 209,"At": 210,"Rn": 222,"Fr": 223,"Ra": 226.0254,"Ac": 227.0278,"Pa": 231.0359,"Th": 232.0381,"Np": 237.0482,"U": 238.029,"Pu": 242,"Am": 243,"Bk": 247,"Cm": 247,"No": 250,"Cf": 251,"Es": 252,"Hs": 255,"Mt": 256,"Fm": 257,"Md": 258,"Lr": 260,"Rf": 261,"Bh": 262,"Db": 262,"Sg": 263,"Uun": 269,"Uuu": 272,"Uub": 277 }

def seperate_string_number(string):
    previous_character = string[0]
    groups = []
    newword = string[0]
    for x, i in enumerate(string[1:]):
        if i.isalpha() and previous_character.isalpha():
            newword += i
        elif i.isnumeric() and previous_character.isnumeric():
            newword += i
        else:
            groups.append(newword)
            newword = i

        previous_character = i

        if x == len(string) - 2:
            groups.append(newword)
            newword = ''
    return groups

def seperate_glued_elements(chem_list):
    temp1 = []
    for item in chem_list:
        if item.isnumeric():
            temp1.append(int(item))
        else:
            temp1.append(item)
    temp2 = []
    for item in temp1:
        if type(item) == str:
            if item.isalpha():
                temp3 = re.findall('[A-Z][^A-Z]*', item)
                for subitem in temp3:
                    temp2.append(subitem)
            else:
                temp2.append(item)
        else:
            temp2.append(item)
    return temp2

def get_subformullas(chem_list):
    subformula_list = []
    temp = []
    switch = False
    lastWasSub = False
    for item in chem_list:
        if type(item) == str:
            if (item) == "(":
                switch = True
        if switch:
            temp.append(item)
        if type(item) == str:
            if (item) == ")":
                switch = False
                lastWasSub = True
        if type(item) == int:
            if lastWasSub:
                temp.append(item)
                lastWasSub = False
                subformula_list.append(temp)
                temp = []
    return subformula_list

def flatten(chem_list):
    substring = ''
    for item in chem_list:
        substring += f'{item}'
    return substring

def data_clean(chem_list):
    multiplier = 1
    temp = chem_list
    if chem_list[0] == "(":
        multiplier = chem_list[len(chem_list)-1]
        chem_list.pop()
        temp = [i for i in chem_list if i != '(' and i != ')']
    return temp, multiplier

def calculate_part(chem_list, total_multiplier):
    mass = 0
    i = 0
    while (i<len(chem_list)):
        multiplier = 1
        char = chem_list[i]
        if (i+1<len(chem_list)):
            if type(chem_list[i+1]) == int:
                multiplier = chem_list[i+1]
                i+=1
        mass += atomic_mass[char]*multiplier
        i+=1
    return mass*total_multiplier
    

def main_calculation(chem_string):
    testformula = chem_string
    parsed_formula = seperate_glued_elements(seperate_string_number(testformula))
    subformulas = get_subformullas(parsed_formula)

    main_formula = chem_string
    for subformula in subformulas:
        main_formula = main_formula.replace(flatten(subformula),'')
    main_formula = seperate_glued_elements(seperate_string_number(main_formula))

    formulas = [data_clean(main_formula)]
    for formula in subformulas:
        formulas.append(data_clean(formula))

    total_mass = 0
    for formula in formulas:
        total_mass += calculate_part(formula[0], formula[1])
    return total_mass

def main():
    formula = ""
    while True:
        formula = input("Input a valid chemical formula or type \"END\" to stop: ")
        if formula == "END":
            break
        try:
            print(f"\n{formula} has a mass of : ~{main_calculation(formula)}\n")
        except:
            print("Improper input!")

main()
© www.soinside.com 2019 - 2024. All rights reserved.