user3507825
user3507825

Reputation: 451

How do I determine between which two array indexes a number lies

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

Answers (3)

Sriram Sakthivel
Sriram Sakthivel

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

Grant Winney
Grant Winney

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

David
David

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

Related Questions