C#中如何将非均匀int范围高效映射到指定字符串,无需手动编写百余条判断?
实现方案
核心思路
采用权重前缀和 + 二分查找的方案,只需要维护权重配置即可,无需手动写大量范围判断,查找效率为O(log n),113个元素最多仅需7次匹配即可得到结果。
具体实现步骤
- 第一步:定义和角色一一对应的权重数组,权重大小直接对应选中概率,总权重和固定为
100000(刚好覆盖你生成的0~99999的val范围)
比如你给出的示例对应的前三个权重为:- names[0] 权重1001(覆盖0~1000共1001个数值)
- names[1] 权重250(覆盖1001~1250共250个数值)
- names[2] 权重500(覆盖1251~1750共500个数值)
后续想要降低某个角色的概率,直接调小对应权重值即可。
- 第二步:预计算前缀和数组,每个元素存储到当前索引为止的权重总和减1(和示例的范围上限对齐)
- 第三步:拿到val后,用二分查找在前缀和数组中找到第一个大于等于val的元素索引,即为目标角色的下标
C# 代码示例
// 预定义配置:113个角色的权重,总和为100000 int[] weights = new int[113] { 1001, 250, 500, /* 剩下110个权重自行配置 */ }; // 预计算前缀和数组,程序启动时计算一次即可 int[] prefixSum = new int[113]; prefixSum[0] = weights[0] - 1; for (int i = 1; i < weights.Length; i++) { prefixSum[i] = prefixSum[i - 1] + weights[i]; } // 运行时查找逻辑 int val = // 你生成的0~99999的数值 int index = Array.BinarySearch(prefixSum, val); // 二分查找返回负数说明无精确匹配,取位反得到第一个大于val的元素索引 if (index < 0) { index = ~index; } string name = names[index];
优势说明
- 配置和逻辑分离:调整概率只需要修改weights数组的数值,不需要修改判断逻辑
- 性能足够:哪怕后续角色数量扩容到上千个,查找速度也不会明显下降
- 避免手写范围判断的人为错误,不会出现漏判、边界值匹配错误问题
内容的提问来源于stack exchange,提问作者ShadowSeal
相关产品推荐
相关产品推荐

