給定一個分子的形式"FA0.85MA0.15Pb(I0.85Br0.15)3"。我需要一本帶有結果的字典("FA":"0.85", "MA":"0.15", "Pb":"1.00", "I":"2.55", "Br":"0.45")。
這是通過將括號內的數字(整數和浮點數)與括號外的整數相乘,然后將每一對分開來獲得的。它還包括為沒有提及成分值的元素(例如此處的 Pb)賦予值,應賦予值“1.00”。
我怎樣才能用 Python 做到這一點?
我有一堆這樣的分子,我想創建一個包含所有這些元素及其組成的資料框,用于元素分析。
注意:不會有任何嵌套括號。所有的組合在結構上都與我上面展示的例子相似,例如"Cs0.05(MA0.17FA0.83)0.95Pb(I0.83Br0.17)3", "CH3NH3PbI3", "(CH3NH3)3Bi2I9"。
uj5u.com熱心網友回復:
該實作首先將字串決議為標記。小型狀態機處理缺失值令牌和括號和乘數。
import re
s = "FA0.85MA0.15Pb(I0.85Br0.15)3"
# t0, t1, token type states
t0 = None; token = ''; token_list = []
for c in s ' ':
if re.match('^[a-zA-Z_] $',c): t1 = "N"
elif re.match('^[0-9.] $',c): t1 = "V"
elif re.match('^[\(] $',c): t1 = "O"
elif re.match('^[\)] $',c): t1 = "C"
else: t1 = 'E'
if not t1 == t0:
# a token is complete
if t0 == 'V': token = float(token)
token_list.append([t0,token])
if t0 == 'N' and not t1 == 'V': # insert value token of 1.0
token_list.append(['V',1.0])
if t0 == 'V' and token_list[-2][0] == 'C':
mult = token_list.pop()
l = len(token_list)
for i in range(0, l):
if token_list[l-i-1][0] == 'O': break # muliplier scope terminates
elif token_list[l-i-1][0] == 'V':
token_list[l-i-1][1] *= mult[1]
t0 = t1; token = ''
token = token c
# clean list
token_list_final = []
for item in token_list[1:]:
if item[0] == 'N' or item[0] == 'V':
token_list_final.append(item)
token_list_final
以上給出了清理后的令牌串列:

可以使用以下方法將其進一步處理為資料框:
V = [ item[1] for item in token_list_final[1::2]]
N = [ item[1] for item in token_list_final[ ::2]]
df = pd.DataFrame([N, V]).T
給予:

uj5u.com熱心網友回復:
,regex我們可以找到并拆分專案。這里有兩個函式可以做到這一點,第一個函式找到帶有系數的括號,第二個函式從字串中找到帶有系數的分子。
所以從字串中洗掉括號并找到并添加分子(不帶括號)。然后對括號中的字串做同樣的作業,然后在括號系數中乘以分子的系數,最后將這些新分子添加到總分子中。
import re
def find_molecules(mol):
# find moleculars
mols = re.findall(r'([A-Z][a-z]?)(\d \.?\d |\d )?', mol)
# fix the non-number molecules
for i in range(len(mols)) :
mol = mols[i]
if not mol[1] :
mols[i] = (mol[0], '1')
# convert to numeric
mols = [(mol[0], float(mol[1])) for mol in mols]
return mols
def find_brackets(mol):
brks = []
# find and split brackets
for br in re.finditer(r'[\(](. )[\)](\d \.?\d |\d )', mol, re.I):
# remove bracker from string
mol = mol.replace(br[0], '')
brks.append( (br[1], float(br[2])) )
return brks, mol
def main(molecular):
data = []
# find and split the the brackets
brks, mol = find_brackets(molecular)
# add the main molecules
data.extend(find_molecules(mol))
# add the molecules that are in brackets
for br in brks:
# get molecules in bracket
mols = find_molecules(br[0])
# multiple the coefficient
mols = [(mol[0], br[1] * mol[1]) for mol in mols]
# add the mols
data.extend(mols)
print(data)
main("MAPbI3")
main("FA0.85MA0.15Pb(I0.85Br0.15)3")
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/497566.html
下一篇:從Python字典中訪問多個資料
