使用C#检查一组变化的整数范围

时间:2019-01-22 12:36:51

标签: c# integer range

填写表格时,用户需要指定一个金额。然后在大约4到6范围内检查此数量。然后将所选范围保存在数据库中。 原始金额将不会存储(出于非技术原因)。范围之间没有重叠,例如:

  • 0-999
  • 1000-1999
  • 2000-4999
  • 5000-9999
  • 10000-higher

棘手的部分是这些范围不是一成不变的。可以进行更改,也可以添加其他范围以进一步指定“ 10000及更高”范围。这些更改将发生两次,并且无法避免。由于无法将特定范围保存到数据库,因此需要存储旧范围。

用于检查一组不断变化的范围的最有效的C#数据结构是什么?

我的研究包括:

  • One of the answers here建议使用C#7在switch语句中可以使用一组固定的整数范围。但是,不可能向switch语句动态添加案例和/或从switch语句删除案例。

  • This question建议使用Enumerable.Range并不是最有效的方法。

3 个答案:

答案 0 :(得分:1)

这里的一种简单方法是将较低频段的值存储在数组中,并将其传递给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;
}

测试代码:

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));

如果有很多频段,这不是最快的方法,但是如果只有几个频段,这可能足够快。

(如果有很多乐队,您可以使用二进制搜索来找到合适的乐队,但我认为这样做会过分杀伤了。)

答案 1 :(得分:1)

您可以对下界进行排序,例如

// 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)
};

,然后找到正确的组(基于 0的

   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

答案 2 :(得分:0)

由于有关如何找到正确范围的答案已经很多,因此我想解决持久性问题。

我们在这里有什么?

  1. 您无法保留确切的值。 (不允许)
  2. 通过将值拟合到一个范围内,将使它们“模糊”。
  3. 这些范围可以(并且将会)随着时间的推移在范围和数量上变化。

因此,我可能要做的是在数据库中明确地将上限和下限持久化。 这样,如果范围更改,则旧数据仍然正确。您无法“转换”为新范围,因为您不知道它是否正确。因此,您需要保留旧的值。更改后的任何新条目都将反映新范围。

人们可以想到标准化,但是老实说,我认为这会使问题变得更加复杂。我只会考虑如果好处(更少的存储空间)将大大超过复杂性问题。