Closest array value?

What’s a good way to determine which number is closest to which? As shown, 775 is closest to which array value?


$Number = 775;
$Sizes = array(100, 500, 900, 2500);


Here’s one way to do it:


function getClosestSize($sizes, $number)
{
    sort($sizes);
    $prevDistance = abs($sizes[0] - $number);

    for ($i = 1; $i < count($sizes); $i++)
    {
        $currentDistance = abs($sizes[$i] - $number);
        if ($prevDistance < $currentDistance)
        {
            return $sizes[$i-1];
        }
        else
        {
            $prevDistance = $currentDistance;
        }
    }
}

Note that I’ve chosen to sort the array first, to make sure the sizes run in sequence, but you may not need that if your array of sizes is fixed.
I wouldn’t be surprised if someone else here came up with a cleverer solution though.

Actually, I’ve just realised there’s a bug in that function… if $number is closest to the last size in the array, you don’t get any output. Adding this line to the end of the function fixes it:

return end($sizes);

You’re only interested in the two values immediately surrounding the number, so it makes little sense to walk the entire array and do calculations on each step.

First, sort the array, as fretburner suggested.
Second, check the edge cases: If the target is lower than the first element of the array, return element 0. If the target is greater than or equal to the last element of the array, return end($array).
Third, $i = 1; while($array[$i] < $target) { $i++; }
Now you’ve found the first value that is bigger than your target.
Fourth Return (($array[$i]-$target) > abs($array[$i-1]-$target)) ? $array[$i-1] : $array[$i];

EDIT: There’s no need for the abs() function on the first half of this condition; as the $array[$i] element is guaranteed to be greater than or equal to your target, the value of ($array[$i]-$target) is guaranteed to be positive or zero.

Thanks StarLion, I thought there was probably something I was missing. Checking for the edge cases first is a great idea - as you say, my function ends up traversing the whole array if the target is closest to (or greater than) the biggest value.