如何处理xA+yB格式输入:生成字典、校验元素并转换格式?
解决思路与代码实现
先拆解输入字符串,再精准提取每个元素的系数与符号,完成合法性校验后,最后拼接成目标格式输出。
1. 拆分输入字符串
用split('+')把输入按加号拆分成单个元素项,同时用strip()处理可能存在的空格(比如输入2X + 4Y的情况),示例:"2X+4Y"会处理成["2X", "4Y"]。
2. 提取系数与元素符号
用正则表达式可以完美区分数字和字母部分,适配单/双字母元素符号与正整数系数的规则,正则表达式为:r'^(\d+)([A-Za-z]{1,2})$',其中:
(\d+):匹配1个及以上数字,确保系数是正整数的基础格式([A-Za-z]{1,2}):匹配1到2个大小写字母,覆盖所有合法元素符号长度
用re.match匹配每个元素项,即可提取出系数字符串和元素符号。
3. 校验与构建映射字典
遍历每个拆分后的项,完成以下核心校验:
- 系数校验:将提取的数字转成整数,判断是否大于0,同时捕获转整数失败的情况(比如输入非数字系数)
- 符号合法性校验:将提取的符号统一转成大写,与给定的
symbol字典键匹配,确保是合法元素 - 符号唯一性校验:检查符号是否已存在于映射字典中,避免重复元素
用字典存储「小写符号: 系数」的映射,另外用列表记录元素出现顺序,保证最后拼接的顺序与输入一致。
完整可运行代码
import re def process_chemical(input_str, valid_symbols): # 拆分输入并清理空格 elements = [item.strip() for item in input_str.split('+')] symbol_coeff = {} element_order = [] for elem in elements: # 匹配系数与元素符号 match = re.match(r'^(\d+)([A-Za-z]{1,2})$', elem) if not match: raise ValueError(f"格式错误:{elem} 不符合「正整数+元素符号」的要求") coeff_part, symbol = match.groups() # 校验系数为正整数 try: coeff = int(coeff_part) if coeff <= 0: raise ValueError(f"系数必须是正整数,当前为:{coeff_part}") except ValueError: raise ValueError(f"{coeff_part} 不是有效的正整数系数") # 校验元素符号合法性 symbol_upper = symbol.upper() if symbol_upper not in valid_symbols: raise ValueError(f"元素符号 {symbol} 不在合法列表中") # 检查符号是否重复 symbol_lower = symbol.lower() if symbol_lower in symbol_coeff: raise ValueError(f"元素符号 {symbol} 重复出现") # 存入映射表与顺序记录 symbol_coeff[symbol_lower] = coeff element_order.append(symbol_lower) # 按输入顺序拼接结果 return ''.join([f"{sym}{coeff}" for sym, coeff in zip(element_order, [symbol_coeff[s] for s in element_order])]) # 示例使用 valid_symbols = {"X": "元素X", "Y": "元素Y", "Zn": "锌", "Fe": "铁"} test_input = "2X+4Y+1Zn" try: print(process_chemical(test_input, valid_symbols)) # 输出: x2y4zn1 except ValueError as e: print(f"错误:{e}")
关键细节说明
- 正则匹配严格限制元素项格式,直接拒绝
X2这种字母在前的错误输入 - 大小写兼容:不管输入符号是大写、小写还是混合格式(比如
zN),都会统一转成大写校验合法性,转成小写用于输出 - 保留输入顺序:用
element_order列表记录元素出现先后,避免字典无序导致输出顺序混乱 - 全面错误处理:覆盖格式错误、无效系数、非法符号、重复符号等常见问题场景
内容的提问来源于stack exchange,提问作者Ursula_G
相关产品推荐
相关产品推荐

