繁体   English   中英

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

[英]Checking against a changing set of integer ranges using C#

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

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

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

对于一组变化的范围,最有效的C#数据结构是什么?

对于我的研究,我包括:

  • 此处的答案之一表明,使用C#7,可以在switch语句中使用一组固定的整数范围。 但是,不可能向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;
}

测试代码:

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

然后找到正确的组(从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

既然已经有关于如何找到正确范围的好答案,我想解决持久性问题。

我们有什么在这里?

  1. 您不能保留确切的值。 ( 不允许 )
  2. 值将通过使它们适合范围而被“模糊”。
  3. 这些范围可以(并且将)随着时间的推移在范围和数量上变化。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM