Reputation: 451
I've got some code that I've worked on that is functional but I feel I'm doing it in a very obtuse way.
I have a fixed size array of 13 elements. The array is populated from a SQL table. If given a number, I'd like to know between which two array indexes the number belongs.
For example: If my number is 500 and I have the following elements: -500, -400, -255, -89, 77, 243, 409, 575, 741, 907, 1073, 1500, 2000
...500 would be between elements 6 and 7. (409 and 575)
I've written a fairly brute force method for doing this using IF statements, code below. I basically create a second array and I use the IF statements to check the number against the first array. Note - I'm ignoring the case where the number is greater than the the max or min array numbers. I've searched for an array method that can search between indexes to no avail. Any ideas on how I can do this more efficiently? Thank you.
int[] deviations = new int[13] { -500, -400, -255, -89, 77, 243, 409, 575, 741, 907, 1073, 1500, 2000 };
int[] arrayCheck = new int[12];
Int64 num = 500;
Console.WriteLine("The number is: {0}", num);
if ((num >= deviations[0]) && (num < deviations[1]))
{arrayCheck[0] = 1;}
else { arrayCheck[0] = 0;}
if ((num >= deviations[1]) && (num < deviations[2]))
{arrayCheck[1] = 1;}
else { arrayCheck[1] = 0;}
if ((num >= deviations[2]) && (num < deviations[3]))
{ arrayCheck[2] = 1; }
else { arrayCheck[2] = 0; }
if ((num >= deviations[3]) && (num < deviations[4]))
{ arrayCheck[3] = 1; }
else { arrayCheck[3] = 0; }
if ((num >= deviations[4]) && (num < deviations[5]))
{ arrayCheck[4] = 1; }
else { arrayCheck[4] = 0; }
if ((num >= deviations[5]) && (num < deviations[6]))
{ arrayCheck[5] = 1; }
else { arrayCheck[5] = 0; }
if ((num >= deviations[6]) && (num < deviations[7]))
{ arrayCheck[6] = 1; }
else { arrayCheck[6] = 0; }
if ((num >= deviations[7]) && (num < deviations[8]))
{ arrayCheck[7] = 1; }
else { arrayCheck[7] = 0; }
if ((num >= deviations[8]) && (num < deviations[9]))
{ arrayCheck[8] = 1; }
else { arrayCheck[8] = 0; }
if ((num >= deviations[9]) && (num < deviations[10]))
{ arrayCheck[9] = 1; }
else { arrayCheck[9] = 0; }
if ((num >= deviations[10]) && (num < deviations[11]))
{ arrayCheck[10] = 1; }
else { arrayCheck[10] = 0; }
if ((num >= deviations[11]) && (num < deviations[12]))
{ arrayCheck[11] = 1; }
else { arrayCheck[11] = 0; }
int arrayIndex = Array.IndexOf(arrayCheck, 1);
Console.WriteLine("The num is between array indexes: {0} and {1}", arrayIndex, arrayIndex + 1);
Upvotes: 1
Views: 181
Reputation: 73502
If array is sorted, Array.BinarySearch is the way to go.
int[] deviations = new int[13] { -500, -400, -255, -89, 77, 243, 409, 575, 741, 907, 1073, 1500, 2000 };
var index = Array.BinarySearch(deviations,500);
if(index >= 0)
{
//Found at index
}
else
{
int expectedindex = ~index;
//Should fall in expectedindex
}
Array.BinarySearch
returns the index of the specified value in the specified array, if value is found. If value is not found and value is less than one or more elements in array, a negative number which is the bitwise complement of the index of the first element that is larger than value. If value is not found and value is greater than any of the elements in array, a negative number which is the bitwise complement of (the index of the last element plus 1).
So when this method returns a negative value, that means given value is not found. but the bit-wise complement of the expected index of the element is returned. Bitwise complement works by changing the bits representation of 1 to 0 and 0 to 1, We make use of ~ operator to turn the bitwise complemented number back to original.
Upvotes: 8
Reputation: 66511
You could use the following two LINQ
statements:
var previousIndex = deviations.Select((d, idx) => new { d, idx })
.Last(x => x.d <= num).idx;
var nextIndex = deviations.Select((d, idx) => new { d, idx })
.First(x => x.d >= num).idx;
You might want to use LastOrDefault()
and FirstOrDefault()
if you're worried about being below the smallest number or above the largest.
Upvotes: 2
Reputation: 34573
Assuming your array is already sorted, can't you just loop through the array?
(Not tested code)
var foundIndex = -1;
for ( var i = 0; i < deviations.GetUpperBound(0); i++ )
{
if ( num >= deviations[i] && num < deviations[i+1] )
{
foundIndex = i;
break;
}
}
Upvotes: 0