解析化学式

Chr*_*jær 21 java chemistry

我正在尝试为一个应用程序编写一个方法,它采用像"CH3COOH"这样的化学式,并返回一些充满符号的集合.

CH3COOH会返回[C,H,H,H,C,O,O,H]

我已经有了一些有点工作的东西,但它非常复杂并且使用了大量嵌套if-else结构和循环的代码.

有没有办法可以通过使用String.split的某种正则表达式或者其他一些简单的代码来实现这一点?

And*_*lke 31

我已经开发了几个关于如何解析分子式的系列文章,包括更复杂的公式如C6H2(NO2)3CH3.

最近的一篇是我在PyCon2010上的演讲" PLY和PyParsing ",我将这两个Python解析系统用分子公式评估器作为我的样本问题进行比较.甚至还有我的演示视频.

该演示文稿基于我使用ANTLR开发分子式分析器的三篇系列文章.在第3部分中,我将ANTLR解决方案与PLY和PyParsing中的手写正则表达式解析器和解决方案进行了比较.

regexp和PLY解决方案最初是在两部分系列中开发的,介绍了在Python中编写解析器的两种方法.

正则表达式解决方案和基本ANTLR/PLY/PyParsing解决方案使用正则表达式,如[AZ] [az]?\ d*来匹配公式中的术语.这就是@David M所建议的.

这是用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
Run Code Online (Sandbox Code Playgroud)

当我运行它(硬编码使用醋酸,CH3COOH)时,我得到了

['C', 'H', 'H', 'H', 'C', 'O', 'O', 'H']
Run Code Online (Sandbox Code Playgroud)

请注意,这一小段代码假定分子式是正确的.如果你给它类似"## $%^ O2#$$#"那么它会忽略它不知道的字段并给出['O','O'].如果你不想要那么你就必须让它更健壮.

如果你想支持更复杂的公式,比如C6H2(NO2)3CH3,那么你需要了解一下树数据结构,特别是(如@Roman所指出的),抽象语法树(通常称为AST).这太复杂了,不能进入这里,所以请看我的谈话和论文了解更多细节.


Dav*_*d M 24

假设它正确大写,则等式中的每个符号都匹配此正则表达式:

[A-Z][a-z]*\d*
Run Code Online (Sandbox Code Playgroud)

(对于化学挑战,元素的符号始终是大写字母,后跟可选的小写一个或可能两个 - 例如汞的汞)

您可以捕获元素符号和组中的数字,如下所示:

([A-Z][a-z]*)(\d*)
Run Code Online (Sandbox Code Playgroud)

所以,是的,从理论上讲,这将是正则表达式可以帮助的东西.如果你正在处理像C 6 H 2(NO 2)3(CH 3)3这样的公式,那么你的工作当然有点难......


Rom*_*man 12

如果您只需要处理简单的情况,那么使用正则表达式的解决方案是最好的方法.否则,您需要构建类似抽象语法树的内容并对其进行评估或使用波兰表示法.

例如,TNT公式C6H2(NO2)3CH3应该表示如下:

(+ (* C 6) (* H 2) (* (+ N (* O 2)) 3) C (+ H 3))
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案是炸药 (13认同)