Reputation: 25
Previously I asked a question as to how to separate characters in a string according to capital letters, or spaces. It was immediately answered. Working on the same piece of code and now I was wondering if it is possible to read an input and ignore integers, and later use it.
For example if the string is H2O, times the value of H twice and then add the value of O.
How to read two characters from an input string?
^^That's the link to my previous question I asked on same code, if useful.
import re
atomMass_Table = {'H': 1.00797, 'He': 4.00260, 'B': 10.81,'C': 12.011, 'N': 14.067, 'O': 15.9994,'F':
18.998403,'P': 30.97376, 'S': 32.06, 'K':39.0983, ' ': 0, None: 0}
TotalMass=0
elements=[ ]
mol=input("Enter a molecule:")
elements = re.findall('[A-Z][^A-Z]*', mol)
for a in elements:
if a == int:
element=None
atomicMass=atomMass_Table.get(a)
TotalMass=TotalMass+atomicMass
print (TotalMass)
Hope I'm not being too confusing :)
Upvotes: 1
Views: 354
Reputation: 178
I extended a bit your Request and added a Class for each molecule.
A Class contains of three attributes:
the class could be extended with a drawing of the molecule or other features.
The Class:
class molecule:
def __init__(self, raw_element, atom_mass_table):
self.amt = atom_mass_table
self.raw_element = raw_element
self.molecule_structur = self.get_struc()
self.molecule_mass = self.cal_mass()
def get_struc(self):
return [self._split_nodes(e) for e in self._split_in_nodes()]
def cal_mass(self):
sum = 0
for i in self.molecule_structur:
sum += self.amt[i[0]] * i[1]
return sum
def _split_nodes(self, node):
s = ""
n = ""
for l in node:
if l.isalpha():
s += l
elif l.isdigit():
n += l
if n is None:
n = 1
return (s, int(n))
def _split_in_nodes(self):
new_el = [e.isupper() for e in self.raw_element]
el_str = []
pos = 0
for _ in range(sum(new_el)):
if True in new_el[pos+1:]:
end = pos + new_el[pos+1:].index(True)+1
else:
end = len(new_el)
el_str.append(self.raw_element[pos:end])
pos = end
return el_str
The Class only needs:
So to test the code:
if __name__ == "__main__":
element = input("Please enter your Molecule: ")
molecule = Molecule(element, atom_mass_table)
print(molecule.molecule_structur)
print(molecule.molecule_mass)
Input:
Please enter you Molecule: C32H128O64
Output:
[('C', 32), ('H', 128), ('O', 64)]
1537.33376
Hope it helps and when you further improve this Application, you can invite me to you GitHub Project.
Upvotes: 0
Reputation: 1298
There are two solutions for you. I don't understand the solution of Thomas, but alec's solution is acceptable. However, it can't work if you have something like "C12H22O11". I give a solution which can fix it, take a look.
atomMass_Table = {'H': 1.00797, 'He': 4.00260, 'B': 10.81,'C': 12.011, 'N': 14.067,
'O': 15.9994,'F': 18.998403,'P': 30.97376, 'S': 32.06, 'K':39.0983, ' ': 0, None: 0, 'd': 0}
TotalMass=0
elements=[ ]
mol=input("Enter a molecule:")
if not mol[-1].isdigit():
mol += '1'
mol += 'd'
number = []
for a in mol:
if a.isdigit():
number.append(a)
else:
if not number:
value = atomMass_Table.get(a)
else:
TotalMass += value * int(''.join(number))
value = atomMass_Table.get(a)
number = []
print (TotalMass)
The solution for H2O is 18.01534 and C12H22O11 is 342.30074. Hope this help!
Upvotes: 1
Reputation: 6112
Use isalpha()
to check if the element only contains letters. If not, you can use string slicing to get the value of the first character from the dictionary, and multiply by the second character.
atomMass_Table = {'H': 1.00797, 'He': 4.00260, 'B': 10.81,'C': 12.011, 'N': 14.067, 'O': 15.9994,'F':
18.998403,'P': 30.97376, 'S': 32.06, 'K':39.0983, ' ': 0, None: 0}
TotalMass = 0
mol = input("Enter a molecule: ")
elements = re.findall('[A-Z][^A-Z]*', mol)
for a in elements:
if a.isalpha():
TotalMass += atomMass_Table.get(a)
else:
TotalMass += atomMass_Table.get(a[0]) * int(a[1])
print(TotalMass)
Example:
Enter a molecule: H2O
18.01534
>>>
Upvotes: 1
Reputation: 21
What about this?
import re
atom_masses = {'H': 1.00797, 'He': 4.00260, 'B': 10.81, 'C': 12.011, 'N': 14.067, 'O': 15.9994, 'F':
18.998403, 'P': 30.97376, 'S': 32.06, 'K': 39.0983, ' ': 0, None: 0}
total_mass = 0
elements = []
mol = input("Enter a molecule:")
parts = re.findall('([A-Z][a-z]?)(\d)*', mol)
print(parts)
for element, count in parts:
if count == '':
count = 0
atomic_mass = atom_masses.get(element)
total_mass = total_mass + atomic_mass * float(count)
print (total_mass)
I changed the regex to divide the string into separate atoms and their count. It has to be a capital letter followed by an optional small letter and an optional number.
Additionally, i changed the variable name because they should be in small letter.
Upvotes: 1