Reputation: 1373
Being new in Python... I want to design a program to calculate the atomic mass, given a molecule like this 'C14-H10-O'.
(I know, there are very beautiful programs created already but I want to create my own program and feel proud of my self.)
My code is almost finished BUT I have found a problem I cant solve.
Here is my code:
masas = {'H': 1.007825, 'C': 12.01, 'O': 15.9994,
'N': 14.0067, 'S': 31.972071, 'P': 30.973762}
elements_list = ['H','C','O', 'N', 'S','P']
def calcula_masa_atomica(molecula):
"""
Calcula la masa atomica de una molecula
"""
import re
masa = 0.0
#Primero creamos los
molecula = re.sub('[-]', '', molecula) #Remove "-"
molecula = (re.split('(\d+)',molecula))#split numbers and elements
for i, ch in enumerate(molecula):
if ch in elements_list: #If the element is in the elements_list,
element_mass = masas.get(ch)# Get the mass of this element
if molecula[i + 1].isdecimal(): #If the inmediately item is decimal
masa += element_mass * int(molecula[i + 1])# Add the mass of this element by the number of times that element is present. In each iteration, the masses of each element will be added and stored in the mass object
# If not, just add that element's mass to the sum.
else:
masa += element_mass
return masa
No problem is the molecule looks like 'C14-H10-O2' BUT if some of the elements have not one digit after the element, Python reply with this error.
IndexError: list index out of range
I know what problem I have is but I do not how I can solve it.
Upvotes: 0
Views: 1715
Reputation: 54168
Using the regex '(([A-Z])([0-9]*))'
you'll find all group in the molecule, like this
'C14-H10-O2' > [('C14', 'C', '14'), ('H10', 'H', '10'), ('O2', 'O', '2')]
'H2O' > [('H2', 'H', '2'), ('O', 'O', '')]
Then iterate over each group, and from atom
find the mass, then multiply by the number (or 1
if there wasn't)
def calcula_masa_atomica(molecula):
masa = 0.0
for group, atom, nb in re.findall(r'(([A-Z])([0-9]*))', molecula):
element_mass = masas.get(atom, 0)
masa += element_mass * int(nb or 1)
return masa
Using list comprehension grammar, it's just :
def calcula_masa_atomica(molecula):
return sum(masas.get(atom, 0) * int(nb or 1) for _, atom, nb in re.findall(r'(([A-Z])([0-9]*))', molecula))
Upvotes: 1