我正在尝试创建一个函数(在Python中),它接受输入(化学式)并分成列表。 例如,如果输入为“HC2H3O2”,则会将其转换为:
molecule_list = ['H', 1, 'C', 2, 'H', 3, 'O', 2]
这个,到目前为止效果很好,但是如果我输入一个带有两个字母的元素,例如钠(Na),它会把它分成:
['N', 'a']
我正在寻找一种方法让我的函数通过字符串查找名为elements的字典中的键。我也在考虑使用正则表达式,但我不确定如何实现它。这就是我现在的功能:
def split_molecule(inputted_molecule):
"""Take the input and split it into a list
eg: C02 => ['C', 1, 'O', 2]
"""
# step 1: convert inputted_molecule to a list
# step 2a: if there are two periodic elements next to each other, insert a '1'
# step 2b: if the last element is an element, append a '1'
# step 3: convert all numbers in list to ints
# step 1:
# problem: it splits Na into 'N', 'a'
# it needs to split by periodic elements
molecule_list = list(inputted_molecule)
# because at most, the list can double when "1" is inserted
max_length_of_molecule_list = 2*len(molecule_list)
# step 2a:
for i in range(0, max_length_of_molecule_list):
try:
if (molecule_list[i] in elements) and (molecule_list[i+1] in elements):
molecule_list.insert(i+1, "1")
except IndexError:
break
# step2b:
if (molecule_list[-1] in elements):
molecule_list.append("1")
# step 3:
for i in range(0, len(molecule_list)):
if molecule_list[i].isdigit():
molecule_list[i] = int(molecule_list[i])
return molecule_list
答案 0 :(得分:5)
怎么样
import re
print re.findall('[A-Z][a-z]?|[0-9]+', 'Na2SO4MnO4')
结果
['Na', '2', 'S', 'O', '4', 'Mn', 'O', '4']
正则表达式解释说:
Find everything that is either
[A-Z] # A,B,...Z, ie. an uppercase letter
[a-z] # followed by a,b,...z, ie. a lowercase latter
? # which is optional
| # or
[0-9] # 0,1,2...9, ie a digit
+ # and perhaps some more of them
这个表达式非常愚蠢,因为它接受任意“元素”,比如“Xy”。您可以将[A-Z][a-z]?
部分替换为以|
分隔的实际元素名称列表,例如Ba|Na|Mn...|C|O
当然,正则表达式只能处理非常简单的公式,以解析像
这样的东西 8(NH4)3P4Mo12O40 + 64NaNO3 + 149NH4NO3 + 135H2O
你需要一个真正的解析器,例如pyparsing(务必查看“示例”下的“化学公式”)。祝你好运!
答案 1 :(得分:2)
这样的表达式将匹配所有感兴趣的部分:
[A-Z][a-z]*|\d+
您可以将其与re.findall
一起使用,然后为没有原子的原子添加量词。
或者你也可以使用正则表达式:
molecule = 'NaHC2H3O2'
print re.findall(r'[A-Z][a-z]*|\d+', re.sub('[A-Z][a-z]*(?![\da-z])', r'\g<0>1', molecule))
输出:
['Na', '1', 'H', '1', 'C', '2', 'H', '3', 'O', '2']
sub
在所有原子后面没有数字后添加1
。
答案 2 :(得分:0)
非正则表达式方法,有点hackish,可能不是最好的,但它有效:
import string
formula = 'HC2H3O2Na'
m_list = list()
for x in formula:
if x in string.lowercase:
m_list.append(formula[formula.index(x)-1]+x)
_ = m_list.pop(len(m_list)-2)
else:
m_list.append(x)
print m_list
['H', 'C', '2', 'H', '3', 'O', '2', 'Na']