C# 在一个列表';s的上限和下限

C# 在一个列表';s的上限和下限,c#,linq,C#,Linq,我现在用下面的方法计算税率 int testValue = 180000; List<TaxBracket> taxes = new List<TaxBracket>(); taxes.Add(new TaxBracket(18199, 0)); //0 to 18199 taxes.Add(new TaxBracket(36999, 19)); //18200 to 36999 taxes.Add(new TaxBracket(79999, Convert.ToDec

我现在用下面的方法计算税率

int testValue = 180000;

List<TaxBracket> taxes = new List<TaxBracket>();
taxes.Add(new TaxBracket(18199, 0)); //0 to 18199
taxes.Add(new TaxBracket(36999, 19)); //18200 to 36999
taxes.Add(new TaxBracket(79999, Convert.ToDecimal(32.50D))); //37000 to 79999
taxes.Add(new TaxBracket(179999, 37)); //80000 to 179999 
taxes.Add(new TaxBracket(180000, 47)); //180000

decimal result = taxes[taxes.Count-1].Value;

for (int i = 0; i < taxes.Count; i++)
{
    if (i == 0)
    {
        if (testValue < taxes[i].Limit)
            result = 0;
    }

    if (i > 0)
    {
        if (testValue < taxes[i].Limit && testValue > taxes[i - 1].Limit) 
        {
            result = taxes[i].Value;
        }
    }
}

Console.WriteLine(result);
int testValue=180000;
列表税=新列表();
增列(新税级(18199,0))//0至18199
增列(新税级(36999,19))//18200至36999
增税(新税级(79999,转换为具体税率(32.50D))//37000至79999
增列(新税级(179999,37))//80000至179999
增列(新税级(180000,47))//180000
十进制结果=税[taxes.Count-1]。值;
for(int i=0;i0)
{
if(testValuetaxes[i-1]。限制)
{
结果=税收[i]。价值;
}
}
}
控制台写入线(结果);

LINQ中是否有其他替代方案可以这样做,而不是使用这种老式方法?看起来很接近,但有点不同。

如果我理解正确,这就是您想要的:

var result = taxes.OrderBy(item => item.Limit)
                  .SkipWhile(item => item.Limit < testValue)
                  .FirstOrDefault()?.Value;
这种方法从不同的方向来看待问题。仅取等于或等于
testValue
的项目,然后对其进行排序,并取第一个项目。

作为Linq替代方案,我建议使用二进制搜索,前提是
税务
已排序:

int index = taxes.BinarySearch(
  new TaxBracket(testValue, -1), // -1: this parameter is ignored
  Comparer<TaxBracket>.Create((left, right) => left.Limit.CompareTo(right.Limit)));

if (index < 0)
  index = ~index - 1; // in between of two indexes

var result = taxes[index].Value;
int index=taxes.BinarySearch(
新的TaxBracket(testValue,-1),/-1:忽略此参数
创建((左,右)=>left.Limit.CompareTo(right.Limit));
如果(指数<0)
索引=~索引-1;//在两个索引之间
var结果=税收[指数]。价值;

当您使用长列表时,二进制搜索非常有用(当Linq提供
O(N)
one时,该算法确保
O(log(N))
复杂性);但是当
很小时,Linq
SkipWhile
(参见吉拉德·格林的回答)更具可读性你能告诉我逻辑:如何
税括号(36999,19))
将从
18200到36999
18200
来自何处?@un lucky-该系列中的每件物品都是该系列中的顶级数字。因此,项0表示所有值,直到达到限制-即18199尝试以下解决方案,如果值大于表中的值,则该解决方案将返回null:decimal?结果=税。其中(x=>testValuex.Value)。LastOrDefault();与@Gilad Green建议的方法相比,这是否更好?@3615-我想说,在较小的系列上,性能并不重要,但在较大的系列上,这更有效:)@Dmitry-不错approach@3615:处理长列表时,二进制搜索更好(时间复杂度更好-
O(log(N))
v.
O(N)
);这是Linq的一个土著(正如问题中所说的)。主要缺点是可读性差。感谢您的澄清!
int index = taxes.BinarySearch(
  new TaxBracket(testValue, -1), // -1: this parameter is ignored
  Comparer<TaxBracket>.Create((left, right) => left.Limit.CompareTo(right.Limit)));

if (index < 0)
  index = ~index - 1; // in between of two indexes

var result = taxes[index].Value;