Question

Je suis en train d'écrire une méthode pour une application qui prend une formule chimique comme « CH3COOH » et retourne une sorte de collection complète de leurs symboles.

CH3COOH reviendrait [C, H, H, H, C, O, O, H]

J'ai déjà quelque chose qui fonctionne un peu, mais il est très compliqué et utilise beaucoup de code avec beaucoup d'emboîtés if-else structures et des boucles.

Est-il possible que je peux le faire en utilisant une sorte d'expression régulière avec String.split ou peut-être dans un autre code simple, brillant?

Était-ce utile?

La solution

En supposant qu'il est capitalisé correctement, chaque symbole dans l'équation correspond à cette expression:

[A-Z][a-z]*\d*

(Pour le défi chimique, le symbole d'un élément est toujours lettre majuscule suivie le cas échéant un minuscule ou peut-être deux - par exemple Hg pour le mercure)

Vous pouvez saisir le symbole de l'élément et le nombre de groupes comme ceci:

([A-Z][a-z]*)(\d*)

Alors oui, en théorie, cela serait quelque chose d'expressions régulières pourraient aider. Si vous avez affaire à des formules comme C 6 H 2 (NO 2 ) 3 (CH 3 ) 3 alors votre travail est bien sûr un peu plus difficile ...

Autres conseils

J'ai développé deux séries d'articles sur la façon d'analyser les formules moléculaires, y compris des formules plus complexes comme C6H2 (NO2) 3CH3.

Le plus récent est ma présentation « PLI et pyparsing » à PyCon2010 où je compare ces deux systèmes d'analyse syntaxique Python à l'aide d'un évaluateur de formule moléculaire comme mon problème échantillon. Il y a même un vidéo de ma présentation .

La présentation était basée sur un série en trois parties des articles je ne le développement d'un analyseur de formule moléculaire en utilisant ANTLR. partie 3 Je compare la solution à ANTLR un analyseur d'expression régulière écrite à la main et des solutions dans PLI et pyparsing.

Les solutions de regexp et PLY ont d'abord été développé dans un série en deux parties sur deux façons d'écrire parseurs en Python.

La solution d'expression rationnelle et la base ANTLR / PLY / solutions pyparsing, utiliser une expression régulière comme [A-Z] [a-z]? \ D * pour correspondre à des termes dans la formule. Voici ce que suggère M @ David.

Voici cela a fonctionné en Python

import re

# element_name is: capital letter followed by optional lower-case
# count is: empty string (so the count is 1), or a set of digits
element_pat = re.compile("([A-Z][a-z]?)(\d*)")

all_elements = []
for (element_name, count) in element_pat.findall("CH3COOH"):
    if count == "":
        count = 1
    else:
        count = int(count)
    all_elements.extend([element_name] * count)

print all_elements

Quand je lance ce (il est codé en dur pour utiliser l'acide acétique, CH3COOH) que je reçois

['C', 'H', 'H', 'H', 'C', 'O', 'O', 'H']

Notez que cette façon peu court de code suppose la formule moléculaire est correcte. Si vous lui donnez quelque chose comme « ## $% ^ O2 # $$ # » il ignore les champs qu'il ne connaît pas et de donner [ « O », « O »]. Si vous ne voulez pas que vous aurez à faire un peu plus robuste.

Si vous voulez soutenir plus de formules compliquées, comme C6H2 (NO2) 3CH3, alors vous aurez besoin de savoir un peu plus sur les structures de données d'arbres, en particulier (comme @Roman souligne), les arbres de syntaxe abstraite (le plus souvent appelés RSHS ). C'est trop compliqué d'entrer dans ici, donc voir mon discours et essais pour plus de détails.

La solution avec des expressions régulières est la meilleure approche si vous avez besoin de traiter uniquement les cas simples. Sinon, vous devez construire quelque chose comme arbre de syntaxe abstraite et de l'évaluer ou de l'utilisation notation polonaise

Par exemple, la formule doit être présentée TNT C6H2(NO2)3CH3 comme:

(+ (* C 6) (* H 2) (* (+ N (* O 2)) 3) C (+ H 3))

Avez-vous regardé dans l'expression de vos formules chimiques dans Chemical Markup Language ? Il est très polyvalent et il y a beaucoup d'outils / téléspectateurs là-bas qui peuvent rendre ces forumulas ou composés chimiques en 2D à la 3D.

Je travaille sur un programme qui nécessite des calculs de masse molaire de formules chimiques, donc j'ai créé une solution qui fonctionne avec une variété de formules.

Par exemple, "(CH3) 16 (Tc (H2O) 3CO (BrFe3 (ReCl) 3 (SO4) 2) 2) 2MnO4" se traduira par "16C 48H 2Tc 12H 6O 2C 2O 4Br 12FE 12Re 12cl 8S 32O Mn 4O »(ce composé est composé, mais bon, ça marche!)

Ce code est écrit en C # et c'est pourquoi je ne l'ai pas posté. Si vous êtes intéressé je peux poster pour vous. En fait, j'ai écrit une réponse complète avant de remarquer la balise java.

Quoi qu'il en soit, il fonctionne en regroupant essentiellement des blocs d'atomes appariés par parenthèse récursive. Il ne gère pas les coefficients tels que 2Pb (mais (Pb) 2 ou Pb2 fonctionne) ou des composés chargés tels que OH-.

En aucun cas, est simple ou élégant. Je ne voulais une solution de travail, donc je sais qu'il ya de meilleures façons (je ne ai même essayé des expressions régulières!). Mais cela fonctionne avec les formules dont j'ai besoin, il convient peut-être aussi le vôtre.

Voici quelques cas de test je l'exécuter sur. Jetez un oeil à eux et laissez-moi savoir si le code C # serait toujours utile pour vous. Le format est (entrée, sortie attendue)

        ("Pb ", " Pb"); 
        ("H ", " H"); 
        ("Pb2 ", " 2Pb"); 
        ("H2 ", " 2H");             
        ("3Pb2 ", " 6Pb");
        ("Pb2SO4", " 2Pb S 4O");                                     
        ("PbH2 ", " Pb 2H");            
        ("(PbH2)2 ", " 2Pb 4H");
        ("(CCC)2 ", " 2C 2C 2C");
        ("Pb(H2)2 ", " Pb 4H");            
        ("(Pb(H2)2)2 ", " 2Pb 8H"); 
        ("(Pb(H2)2)2NO3 ", " 2Pb 8H N 3O"); 
        ("(Ag(Pb(H2)2)2)2SO4 ", " 2Ag 4Pb 16H S 4O");             
        ("Pb(CH3(CH2)2CH3)2", " Pb 2C 6H 4C 8H 2C 6H"); 
        ("Na2(CH3(CH2)2CH3)2", " 2Na 2C 6H 4C 8H 2C 6H");
        ("Tc(H2O)3Fe3(SO4)2", " Tc 6H 3O 3Fe 2S 8O");
        ("Tc(H2O)3(Fe3(SO4)2)2", " Tc 6H 3O 6Fe 4S 16O");
        ("(Tc(H2O)3(Fe3(SO4)2)2)2", " 2Tc 12H 6O 12Fe 8S 32O");
        ("(Tc(H2O)3CO(Fe3(SO4)2)2)2", " 2Tc 12H 6O 2C 2O 12Fe 8S 32O");
        ("(Tc(H2O)3CO(BrFe3(ReCl)3(SO4)2)2)2MnO4", " 2Tc 12H 6O 2C 2O 4Br 12Fe 12Re 12Cl 8S 32O Mn 4O");
        ("(CH3)16(Tc(H2O)3CO(BrFe3(ReCl)3(SO4)2)2)2MnO4", " 16C 48H 2Tc 12H 6O 2C 2O 4Br 12Fe 12Re 12Cl 8S 32O Mn 4O"); 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top