如何实现SAP Idoc中成本中心参考范围的全组合生成?
实现SAP IDoc成本中心字母数字范围的全量展开思路与代码修复
你的核心思路是对的:先提取起止字符串的公共前缀,只处理差异的可变部分,这个方向完全没问题。但现有代码的问题在于:
- 循环条件错误(
i == 0只会执行一次循环) - 没有处理进位场景(比如从
A9跳到AA这种需要前一位递增的情况)
核心实现思路
我们可以把每个可变部分的字符串看作一个自定义进制的数:
- 字符顺序固定为
0-9A-Z,共36个字符,每个字符对应一个0-35的数值 - 将起始和结束的可变字符串转换为对应的十进制数值
- 遍历从起始数值到结束数值的所有整数,再把每个整数转换回对应的字母数字字符串
- 最后把公共前缀和转换后的字符串拼接,得到最终结果
这种方法能完美处理所有进位、跨字符组(数字转字母)的场景,逻辑更清晰也更易维护。
修复后的完整代码
using System; using System.Collections.Generic; using System.Linq; class CostCenterRangeExpander { // 定义固定的字符顺序:先数字0-9,后字母A-Z private static readonly char[] _charSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToArray(); private static readonly Dictionary<char, int> _charToValue = _charSet.Select((c, idx) => new { c, idx }) .ToDictionary(x => x.c, x => x.idx); static void Main(string[] args) { string from = "D3A0"; string to = "D3AC"; // 步骤1:提取公共前缀 string commonPrefix = GetCommonPrefix(from, to); string variableFrom = from.Substring(commonPrefix.Length); string variableTo = to.Substring(commonPrefix.Length); // 步骤2:将可变字符串转换为数值 long fromValue = StringToValue(variableFrom); long toValue = StringToValue(variableTo); // 步骤3:遍历所有数值,转换回字符串并拼接前缀 var result = new List<string>(); for (long val = fromValue; val <= toValue; val++) { string variablePart = ValueToString(val, variableFrom.Length); result.Add(commonPrefix + variablePart); } // 输出结果 foreach (var item in result) { Console.WriteLine(item); } } // 获取两个字符串的最长公共前缀 private static string GetCommonPrefix(string a, string b) { int minLength = Math.Min(a.Length, b.Length); int prefixLength = 0; while (prefixLength < minLength && a[prefixLength] == b[prefixLength]) { prefixLength++; } return a.Substring(0, prefixLength); } // 将字母数字字符串转换为十进制数值 private static long StringToValue(string s) { long value = 0; foreach (char c in s) { value = value * _charSet.Length + _charToValue[c]; } return value; } // 将十进制数值转换为指定长度的字母数字字符串(补前导字符) private static string ValueToString(long value, int length) { char[] chars = new char[length]; for (int i = length - 1; i >= 0; i--) { int remainder = (int)(value % _charSet.Length); chars[i] = _charSet[remainder]; value = value / _charSet.Length; } return new string(chars); } }
代码说明
- 字符映射:用
_charSet定义顺序,_charToValue快速查找字符对应的数值,避免每次遍历查找 - 公共前缀提取:逐字符对比直到找到第一个不同的位置,逻辑简单可靠
- 字符串与数值互转:把可变部分当成36进制数处理,完美解决进位问题
- 长度保持:转换回字符串时强制保持原长度,避免出现短字符串(比如数值0转换为
00而不是0,适配SAP IDoc的格式要求)
测试你的例子
对于输入from="D3A0"、to="D3AC",代码会输出:
D3A0 D3A1 D3A2 D3A3 D3A4 D3A5 D3A6 D3A7 D3A8 D3A9 D3AA D3AB D3AC
完全符合你的需求。
边界情况补充
- 如果起止字符串长度不同:比如
from="A"、to="AA",你需要先统一长度(比如给短字符串补前导0),再执行上述逻辑 - 如果起始值大于结束值:可以先交换两者,再执行遍历
内容的提问来源于stack exchange,提问作者yu_ominae
相关产品推荐
相关产品推荐

