
本文介绍一个健壮的 javascript 函数,用于将标准化学分子式(如 "h2o"、"c6h12"、"cooh")解析为键值对形式的 json 对象,正确处理重复元素(如 cooh 中的两个 o),支持单/双字母元素符号及隐式数量(无数字默认为 1)。
本文介绍一个健壮的 javascript 函数,用于将标准化学分子式(如 "h2o"、"c6h12"、"cooh")解析为键值对形式的 json 对象,正确处理重复元素(如 cooh 中的两个 o),支持单/双字母元素符号及隐式数量(无数字默认为 1)。
化学分子式(如 "H2O"、"COOH"、"Mg(OH)2")看似简单,但其解析逻辑需兼顾元素命名规则(首大写、次小写,如 "Na"、"Cl")、数字连续性("Ca12" 表示钙原子 12 个)、隐式计数("H2O" 中 O 实际为 O1)以及同一元素多次出现时的累加(关键难点:"COOH" 含两个氧原子,必须合并为 "O": 2,而非覆盖或忽略)。
下面是一个经过验证、简洁可靠的实现:
function parseChemicalCompound(chemical) {
const result = {};
let currentElement = "";
let currentCount = "";
for (let i = 0; i < chemical.length; i++) {
const char = chemical[i];
// 大写字母:新元素开始
if (/[A-Z]/.test(char)) {
// 先保存上一个完整元素(如有)
if (currentElement) {
const count = currentCount ? parseInt(currentCount, 10) : 1;
result[currentElement] = (result[currentElement] ?? 0) + count;
}
currentElement = char;
currentCount = "";
}
// 小写字母:追加到当前元素(如 'a' in "Na")
else if (/[a-z]/.test(char)) {
currentElement += char;
}
// 数字:累积计数(支持多位数,如 "12")
else if (/\d/.test(char)) {
currentCount += char;
}
// 其他字符(如括号、空格等)——当前版本跳过;生产环境可按需扩展支持括号分组
else {
console.warn(`Unrecognized character '${char}' at position ${i}. Skipping.`);
}
}
// 处理末尾元素
if (currentElement) {
const count = currentCount ? parseInt(currentCount, 10) : 1;
result[currentElement] = (result[currentElement] ?? 0) + count;
}
return result;
}✅ 关键修复点说明:
- 原始代码使用
result[currentElement] = parseInt(...)是赋值覆盖,导致"COOH"中第二个"O"覆盖第一个,结果为"O": 1。 - 正确做法是累加:
result[currentElement] = (result[currentElement] ?? 0) + count—— 利用空值合并运算符??安全处理未定义键,确保多次出现的同一元素数量正确叠加。 - 移除了冗余且错误的
char === nextChar分支(该逻辑既不必要,也无法解决"COOH"问题;O和O并非相邻,中间隔着H,实际是C-O-O-H,两次O出现在不同循环迭代中)。
? 测试用例验证:
console.log(parseChemicalCompound("H2O")); // { H: 2, O: 1 }
console.log(parseChemicalCompound("C6H12")); // { C: 6, H: 12 }
console.log(parseChemicalCompound("COOH")); // { C: 1, O: 2, H: 1 }
console.log(parseChemicalCompound("NaCl")); // { Na: 1, Cl: 1 }
console.log(parseChemicalCompound("Ca12")); // { Ca: 12 }⚠️ 注意事项与扩展建议:
- 当前函数不支持括号嵌套(如
"Ca(OH)2"),若需完整解析,应引入递归或栈结构处理分组与乘法(如(OH)2→O:2, H:2)。 - 元素符号校验未做强约束(例如不会拒绝
"Xy"),如需高可靠性,可预置 118 个已知元素符号集合进行白名单匹配。 - 返回对象为普通 JS 对象,如需严格 JSON 格式输出,可直接
JSON.stringify(parseChemicalCompound(...))。
该实现平衡了可读性、健壮性与实用性,适用于教学、轻量化学工具或前端数据预处理场景。


















