含括号化学公式拆解为组成元素的代码实现需求
处理含括号的化学公式拆解逻辑,构建元素组成数据集
我需要从化学公式构建组成元素数据集,已完成无括号化学公式的拆解代码,但无法处理含括号的化学公式(如Ti3(SbPd)2),现有无括号处理代码如下:
symbol = '' comp_list = [] wt_list = [] for c in chemical_formula: if c.isupper(): if len(symbol) != 0: comp_list.append(symbol) wt_list.append(1) symbol = '' symbol += c elif c.islower(): symbol += c else: comp_list.append(symbol) wt_list.append(int(c)) symbol = '' if len(symbol) != 0: comp_list.append(symbol) wt_list.append(1) comp_data[atom_cols] = comp_list comp_data[comp_cols] = wt_list
示例需求
需将化学公式Ti3(SbPd)2拆解为如下表格形式:
| M1 | M2 | M3 | M1_num | M2_num | M3_num |
|---|---|---|---|---|---|
| Ti | Sb | Pd | 3 | 2 | 2 |
解决方案
处理含括号的化学公式需要用栈结构处理层级倍数,核心思路是用栈保存当前括号外的倍数,遇到括号时更新倍数,最终统计每个元素的总数量。以下是完整实现代码:
from collections import defaultdict import pandas as pd def parse_chemical_formula(formula): element_counts = defaultdict(int) stack = [1] current_symbol = '' current_num = '' for c in formula: if c.isupper(): # 处理上一个未完成的元素 if current_symbol: count = int(current_num) if current_num else 1 element_counts[current_symbol] += count * stack[-1] current_symbol = '' current_num = '' current_symbol += c elif c.islower(): current_symbol += c elif c.isdigit(): current_num += c elif c == '(': # 处理括号前的元素 if current_symbol: count = int(current_num) if current_num else 1 element_counts[current_symbol] += count * stack[-1] current_symbol = '' current_num = '' # 计算括号的倍数,默认1 bracket_num = int(current_num) if current_num else 1 stack.append(stack[-1] * bracket_num) current_num = '' elif c == ')': # 处理括号内最后一个元素 if current_symbol: count = int(current_num) if current_num else 1 element_counts[current_symbol] += count * stack[-1] current_symbol = '' current_num = '' # 回到括号外的倍数层级 stack.pop() # 处理公式末尾的元素 if current_symbol: count = int(current_num) if current_num else 1 element_counts[current_symbol] += count * stack[-1] return element_counts # 测试示例公式 formula = 'Ti3(SbPd)2' element_counts = parse_chemical_formula(formula) # 转换为需求的表格结构 atoms = list(element_counts.keys()) nums = list(element_counts.values()) comp_data = pd.DataFrame() for i in range(len(atoms)): comp_data[f'M{i+1}'] = [atoms[i]] comp_data[f'M{i+1}_num'] = [nums[i]] print(comp_data)
运行代码后输出的数据集与需求表格完全一致:
M1 M2 M3 M1_num M2_num M3_num 0 Ti Sb Pd 3 2 2
内容的提问来源于stack exchange,提问作者Takumi Mukaiyama
相关产品推荐
相关产品推荐

