Find a matching or closest value in an array Find a matching or closest value in an array php php

Find a matching or closest value in an array


Pass in the number you're searching for as the first parameter and the array of numbers to the second:

function getClosest($search, $arr) {   $closest = null;   foreach ($arr as $item) {      if ($closest === null || abs($search - $closest) > abs($item - $search)) {         $closest = $item;      }   }   return $closest;}


A particular lazy approach is having PHP sort the array by the distance to the searched number:

$num = 3;    $array = array(0, 5, 10, 11, 12, 20);foreach ($array as $i) {    $smallest[$i] = abs($i - $num);}asort($smallest);print key($smallest);


This is high-performance function I wrote for sorted big arrays

Tested, main loop needs only ~20 iterations for an array with 20000 elements.

Please mind array has to be sorted (ascending)!

define('ARRAY_NEAREST_DEFAULT',    0);define('ARRAY_NEAREST_LOWER',      1);define('ARRAY_NEAREST_HIGHER',     2);/** * Finds nearest value in numeric array. Can be used in loops. * Array needs to be non-assocative and sorted. *  * @param array $array * @param int $value * @param int $method ARRAY_NEAREST_DEFAULT|ARRAY_NEAREST_LOWER|ARRAY_NEAREST_HIGHER * @return int */function array_numeric_sorted_nearest($array, $value, $method = ARRAY_NEAREST_DEFAULT) {        $count = count($array);    if($count == 0) {        return null;    }        $div_step               = 2;        $index                  = ceil($count / $div_step);        $best_index             = null;    $best_score             = null;    $direction              = null;        $indexes_checked        = Array();    while(true) {                if(isset($indexes_checked[$index])) {            break ;        }        $curr_key = $array[$index];        if($curr_key === null) {            break ;        }        $indexes_checked[$index] = true;        // perfect match, nothing else to do        if($curr_key == $value) {            return $curr_key;        }        $prev_key = $array[$index - 1];        $next_key = $array[$index + 1];        switch($method) {            default:            case ARRAY_NEAREST_DEFAULT:                $curr_score = abs($curr_key - $value);                $prev_score = $prev_key !== null ? abs($prev_key - $value) : null;                $next_score = $next_key !== null ? abs($next_key - $value) : null;                if($prev_score === null) {                    $direction = 1;                                    }else if ($next_score === null) {                    break 2;                }else{                                        $direction = $next_score < $prev_score ? 1 : -1;                                    }                break;            case ARRAY_NEAREST_LOWER:                $curr_score = $curr_key - $value;                if($curr_score > 0) {                    $curr_score = null;                }else{                    $curr_score = abs($curr_score);                }                if($curr_score === null) {                    $direction = -1;                }else{                    $direction = 1;                }                                break;            case ARRAY_NEAREST_HIGHER:                $curr_score = $curr_key - $value;                if($curr_score < 0) {                    $curr_score = null;                }                if($curr_score === null) {                    $direction = 1;                }else{                    $direction = -1;                }                  break;        }        if(($curr_score !== null) && ($curr_score < $best_score) || ($best_score === null)) {            $best_index = $index;            $best_score = $curr_score;        }        $div_step *= 2;        $index += $direction * ceil($count / $div_step);    }    return $array[$best_index];}
  • ARRAY_NEAREST_DEFAULT finds nearest element
  • ARRAY_NEAREST_LOWER finds nearest element which is LOWER
  • ARRAY_NEAREST_HIGHER finds nearest element which is HIGHER

Usage:

$test = Array(5,2,8,3,9,12,20,...,52100,52460,62000);// sort an array and use array_numeric_sorted_nearest// for multiple searches. // for every iteration it start from half of chunk where// first chunk is whole array// function doesn't work with unosrted arrays, and it's much// faster than other solutions here for sorted arrayssort($test);$nearest = array_numeric_sorted_nearest($test, 8256);$nearest = array_numeric_sorted_nearest($test, 3433);$nearest = array_numeric_sorted_nearest($test, 1100);$nearest = array_numeric_sorted_nearest($test, 700);