Reputation: 427
I'm currently calculating tax rate by the following way
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);
Is there any alternate in LINQ to do this instead of using this old-school approach? Looks pretty close to this but a bit different.
Upvotes: 2
Views: 472
Reputation: 186668
As a Linq alternative I suggest using binary search, providing that taxes
is sorted:
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;
Binary search can be useful when you work with long list (the algorithm ensures O(log(N))
complexity, when Linq provides O(N)
one); but when taxes
is small, Linq SkipWhile
(see Gilad Green's answer) is more readable
Upvotes: 3
Reputation: 37299
If I understood correctly this is what you want:
var result = taxes.OrderBy(item => item.Limit)
.SkipWhile(item => item.Limit < testValue)
.FirstOrDefault()?.Value;
It will order your collection from smallest Limit
to largest and then will Skip
until it reaches a Limit
that is equal or greater than your testValue
. Because collection is ordered then the FirstOrDefault
and it's value.
Or:
var result = taxes.Where(item => item.Limit >= testValue )
.OrderBy(item => item.Limit)
.FirstOrDefault()?.Value;
This way looks at the problem from a different direction. Take only the items that are equal or to testValue
and then order them ant take the first.
Upvotes: 4