C# 使用C检查一组不断变化的整数范围#
填写表单时,用户需要指定金额。然后对照大约4到6个范围检查该金额。然后将选定的范围保存在数据库中。不会存储原始金额(出于非技术原因)。范围之间不会有重叠,例如:C# 使用C检查一组不断变化的整数范围#,c#,integer,range,C#,Integer,Range,填写表单时,用户需要指定金额。然后对照大约4到6个范围检查该金额。然后将选定的范围保存在数据库中。不会存储原始金额(出于非技术原因)。范围之间不会有重叠,例如: 0-999 1000-1999 2000-4999 5000-9999 10000以上 棘手的是,这些范围不是固定不变的。可以进行更改,也可以添加其他范围,以进一步指定“10000及以上”范围。这些变化会发生几次,无法阻止。由于无法将具体金额保存到数据库中,因此需要存储旧范围 对于检查不断变化的范围集,最有效的C#数据结构是什么 我
0-999
1000-1999
2000-4999
5000-9999
10000以上
- 建议使用C#7可以在switch语句中使用一组固定的整数范围。但是,不可能在switch语句中动态添加案例和/或从中删除案例
- 建议使用Enumerable.Range不是最有效的方法
FindBand()
方法,该方法返回一个整数,表示包含该值的频带的索引
例如:
public static int FindBand(double value, double[] bandLowerValues)
{
for (int i = 0; i < bandLowerValues.Length; ++i)
if (value < bandLowerValues[i])
return Math.Max(0, i-1);
return bandLowerValues.Length;
}
如果有很多波段,这不是最快的方法,但是如果只有几个波段,这可能足够快
(如果有很多条带,你可以使用二进制搜索来找到合适的条带,但我认为这样做太过分了。)你可以对下限排序,例如
然后找到正确的组(基于0)
由于关于如何找到正确的范围已经有了很好的答案,我想解决持久性问题 我们这里有什么
人们可以考虑正常化,但老实说,我认为这会使问题变得过于复杂。我只想,如果好处(更少的存储空间)将大大超过复杂性问题。显然,开关不会为你工作。你还可以做些什么,你的第二个问题是指出一种方法,将范围存储在内存中,并遍历它们。无论是数组、列表还是IEnumerable。。扫描任何东西中的5个元素都不会对性能造成巨大影响,除非这是超性能的关键任务。请注意,在C#8中会有一个内置的
范围
类型(我不知道它是否对您有帮助)。您在这里混合了几个问题。1.如何以DB保存“范围”?2.如何处理对范围的更改?这些需要单独处理。由于您无法保存原始工资(我猜是这样的,对吧?),因此在保留范围时会丢失信息。示例:“2031.49”=>“2k-4.999”。现在,如果该范围更改为“1.5k-4.5k”,则旧信息将无效,因为您无法判断初始值是否仍在该范围内。所以,如果你想保持一致,就需要引入“历史”数据。@Fildor我正在研究一种方法来保存数据库中的范围。我尽量只回答一个问题。1.000是1000分隔符,我将在我的问题中更改它。双倍值
-我很有信心我们正在处理货币金额。因此,我建议不要使用double
,尽管在这种情况下可能没有什么区别。是的,使用decimal
类型作为货币,但OP的代码没有为浮点数指定m
后缀,因此它们是double
。同意,我只是想提出这个建议,因为我曾经在从一个重构到另一个重构时遇到很多麻烦。因此,我想省去其他人的麻烦。我决定将所选范围与数据库中可能的范围一起保存为JSON字符串,例如{“ranges”:[10002000500010000],“SelectedRange”:0}
。索引0将转换为范围0-999,索引1将生成1000-2000,以此类推。这样,当选择新范围时,旧数据不会丢失。
double[] bandLowerValues = {0, 1, 2, 5, 10};
Console.WriteLine(FindBand(-1, bandLowerValues));
Console.WriteLine(FindBand(0, bandLowerValues));
Console.WriteLine(FindBand(0.5, bandLowerValues));
Console.WriteLine(FindBand(1, bandLowerValues));
Console.WriteLine(FindBand(1.5, bandLowerValues));
Console.WriteLine(FindBand(2.5, bandLowerValues));
Console.WriteLine(FindBand(5, bandLowerValues));
Console.WriteLine(FindBand(8, bandLowerValues));
Console.WriteLine(FindBand(9.9, bandLowerValues));
Console.WriteLine(FindBand(10, bandLowerValues));
Console.WriteLine(FindBand(11, bandLowerValues));
// or decimal instead of double if values are money
double[] lowBounds = new double[] {
0, // 0th group: (-Inf .. 0)
1000, // 1st group: [0 .. 1000)
2000, // 2nd group: [1000 .. 2000)
5000, // 3d group: [2000 .. 5000)
10000, // 4th group: [5000 .. 10000)
// 5th group: [10000 .. +Inf)
};
int index = Array.BinarySearch(lowBounds, value);
index = index < 0 ? index = -index - 1 : index + 1;
double[] tests = new double[] {
-10,
0,
45,
999,
1000,
1997,
5123,
10000,
20000,
};
var result = tests
.Select(value => {
int index = Array.BinarySearch(lowBounds, value);
index = index < 0 ? index = -index - 1 : index + 1;
return $"{value,6} : {index}";
});
Console.Write(string.Join(Environment.NewLine, result));
-10 : 0
0 : 1
45 : 1
999 : 1
1000 : 2
1997 : 2
5123 : 4
10000 : 5
20000 : 5