使用Regex解析化学式转Dictionary时遇格式错误及键重复问题
解析化学式Regex的常见问题与修复方案
我来帮你搞定这两个报错的问题!先拆解一下你遇到的两个错误原因,再给你修正后的代码:
错误原因分析
- 「输入字符串格式不正确」:你的正则表达式里
(?<Value>[0-9]|() )有问题——当元素后面没有数字时(比如CH里的H),Value分组会匹配到空字符串,直接用int.Parse转空字符串肯定会抛异常。 - 「键已存在于字典中」:
ToDictionary方法会把所有匹配到的键直接存入字典,但像CHHHH这种写法会匹配到4个H键,重复的键自然会触发这个错误,而你需要的是累加同一元素的数量,不是直接覆盖或报错。
修正方案与代码
先修正正则表达式,然后用你熟悉的ContainsKey逻辑来累加元素数量,完美适配CH4和CHHHH这种不同写法:
string chemForm = tbxFormula.Text.ToString(); // 修正后的正则:匹配元素符号(大写开头,可选小写后缀),后面跟可选的数字(0个或多个) string pat = @"(?<Key>[A-Z][a-z]?)(?<Value>\d*)"; var elementCounts = new Dictionary<string, int>(); foreach (Match m in Regex.Matches(chemForm, pat)) { string element = m.Groups["Key"].Value; // 处理数字:如果没有数字(空字符串),默认数量为1,否则转成整数 int count = string.IsNullOrEmpty(m.Groups["Value"].Value) ? 1 : int.Parse(m.Groups["Value"].Value); // 用你熟悉的逻辑累加数量 if (elementCounts.ContainsKey(element)) { elementCounts[element] += count; } else { elementCounts[element] = count; } }
关键细节说明
- 正则
[A-Z][a-z]?:正确匹配所有元素符号,比如C、H、Fe、Na这种大小写组合。 \d*:匹配0个或多个数字,兼容元素后面没有数字的情况(比如CH里的C和H默认数量都是1)。- 循环累加:避免了
ToDictionary的重复键问题,同时实现了你需要的“同一元素多次出现时累加数量”的需求。
如果之后需要处理带括号的复杂化学式(比如(CH2)3),可以再扩展正则和逻辑,但当前代码已经能解决你提到的核心问题啦!
内容的提问来源于stack exchange,提问作者user12136652




