Aabshaar
Aabshaar

Reputation: 25

How to ignore a specific character in a string, and later use it?

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

Answers (4)

MunsMan
MunsMan

Reputation: 178

I extended a bit your Request and added a Class for each molecule.

A Class contains of three attributes:

  • raw_element
  • molecule structure
  • molecule mass

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:

  • raw element description - C12H22O11
  • your provided atom_mass_table - I didn't include it in the class, for easier expansion later on.

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

CuCaRot
CuCaRot

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

alec
alec

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

Thomas Panzeri
Thomas Panzeri

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

Related Questions