如何在不使用正则的前提下提取表达式负数存入数组
解决方案
原有直接按四则运算符拆分的逻辑,会把负数前的负号和作为运算符的减号混淆,导致负号被丢弃,无法正常识别负数。我们可以通过区分负号和减法运算符的逻辑实现无正则的数字提取,判断规则非常简单:只有两种场景下-是负号:
- 它是整个表达式的第一个非空白字符
- 它的前一个非空白字符是
/、*、+、-四个运算符之一
其余场景下的-均为减法运算符,按拆分标记处理即可,完整实现代码如下:
private static readonly char[] validOperators = { '/', '*', '+', '-' }; public static List<double> GetNumbersFromExpression(string inputData) { List<double> numbers = new List<double>(); // 先清除所有空白字符,避免空格干扰判断逻辑 string cleanedInput = new string(inputData.Where(c => !char.IsWhiteSpace(c)).ToArray()); string currentNumber = string.Empty; for (int i = 0; i < cleanedInput.Length; i++) { char c = cleanedInput[i]; // 判断当前字符为负号,而非减法运算符 if (c == '-' && (i == 0 || validOperators.Contains(cleanedInput[i - 1]))) { currentNumber += c; } // 数字或小数点归入当前数字字符串 else if (char.IsDigit(c) || c == '.') { currentNumber += c; } // 遇到运算符则结束当前数字的读取 else if (validOperators.Contains(c)) { if (!string.IsNullOrEmpty(currentNumber)) { numbers.Add(double.Parse(currentNumber)); currentNumber = string.Empty; } } // 可选:非法字符校验,不需要可以删除该分支 else { throw new ArgumentException($"表达式包含非法字符:{c}"); } } // 读取表达式末尾的最后一个数字 if (!string.IsNullOrEmpty(currentNumber)) { numbers.Add(double.Parse(currentNumber)); } return numbers; }
用你提供的示例inputData = "-80 * 5-5"调用该方法,最终得到的数字列表为[-80, 5, 5],符合预期。该方案还有以下适配性:
- 支持识别表达式中间的负数,例如
"5*-3+2"会正确返回[5, -3, 2] - 支持带小数点的浮点数识别,不需要小数可以删除小数点判断逻辑
- 纯字符串遍历实现,无额外依赖,性能和可维护性都高于正则方案
内容的提问来源于stack exchange,提问作者ItachiU
相关产品推荐
相关产品推荐

