views:

54

answers:

2

I'm trying to create a "lookup" column that would return the index of the array value that is equal to or less than the value being looked up. So this is my attempt, which seems to work fine, but I was wondering if there is a cleaner way of doing it ?

// Sorted
float[] ranges = new float[]
  {
     0.8f,
     1.1f,
     2.7f,
     3.9f,
     4.5f,
     5.1f,
  };


private int GetIndex(float lookupValue)
{
    int position = Array.BinarySearch(ranges, lookupValue);
    if (position < 0)
    {
        // Find the highest available value that does not
        // exceed the value being looked up.
        position = ~position - 1;
    }

    // If position is still negative => all values in array 
    // are greater than lookupValue, return 0
    return position < 0 ? 0 : position;
}

Thanks.

+2  A: 

Nope, I think this is a pretty good approach.

The only thing I might change is to make it an extension method on arrays, instead of a private function referring to a class variable. Then it becomes general / not tied to one class, and the syntax is cleaner too: ranges.GetIndex(...)

Something like this:

public static class Extensions
{
    public static int GetIndex<T>(this T[] ranges, T lookupValue)
    {
        // your code here
    }
}

Of course, you'll have to remember this only works on sorted arrays...

tzaman
+1 because extensions are nice, though I would maybe constrain the types so you don't have intellisense popping this GetIndex on an array of some complex data type..
Jimmy Hoffa
+1  A: 

You could use a normal for loop (assuming your data is ordered). Not sure if it's cleaner, but certainly not as effective on lots of data. Personally I would go for the BinarySearch you have.

int GetIndex(IList<float> ranges, float target)
{
    for (int i = 0; i < ranges.Count; i++)
    {
        if(ranges[i] < target) continue;
        if (ranges[i] >= target) return i;
    }
    return 0;
}
Mikael Svenson