SitePoint Sponsor

User Tag List

Results 1 to 5 of 5

Hybrid View

  1. #1
    SitePoint Enthusiast
    Join Date
    Apr 2012
    Posts
    70
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    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?

    PHP Code:
    $Number 775;
    $Sizes = array(1005009002500); 

  2. #2
    Community Advisor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,389
    Mentioned
    45 Post(s)
    Tagged
    12 Thread(s)
    Here's one way to do it:
    PHP Code:
    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.

  3. #3
    Community Advisor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,389
    Mentioned
    45 Post(s)
    Tagged
    12 Thread(s)
    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:
    PHP Code:
    return end($sizes); 

  4. #4
    Keeper of the SFL StarLion's Avatar
    Join Date
    Feb 2006
    Location
    Atlanta, GA, USA
    Posts
    3,748
    Mentioned
    69 Post(s)
    Tagged
    0 Thread(s)
    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.
    Never grow up. The instant you do, you lose all ability to imagine great things, for fear of reality crashing in.

  5. #5
    Community Advisor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,389
    Mentioned
    45 Post(s)
    Tagged
    12 Thread(s)
    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.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •