Если у меня есть массив PHP:
$array
Со значениями:
45,41,40,39,37,31
И у меня есть переменная:
$number = 38;
Как я могу вернуть значение?:
39
Поскольку это самое близкое значение до 38 (подсчет) в массиве?
Привет,
Тэйлора
Если у меня есть массив PHP:
$array
Со значениями:
45,41,40,39,37,31
И у меня есть переменная:
$number = 38;
Как я могу вернуть значение?:
39
Поскольку это самое близкое значение до 38 (подсчет) в массиве?
Привет,
Тэйлора
<?php
function closest($array, $number) {
sort($array);
foreach ($array as $a) {
if ($a >= $number) return $a;
}
return end($array); // or return NULL;
}
?>
Вот высокоуровневый процесс для получения желаемых результатов и работы для любых данных массива:
O(n)
O(n lg n)
(надеюсь)Теперь, предполагая, что массив отсортирован в ASCENDING, этот подход будет работать:
O(n)
И если массив DESCENDING (как в сообщении), выполните действия, описанные выше, но либо:
O(n)
O(n lg n)
(надеюсь)O(n)
Счастливое кодирование.
EDIT опечатка на array_search
Эй... Кажется, достаточно легко. Здесь функция
<?php
$array = array(45,41,40,39,37,31);
function closest($array, $number){
#does the array already contain the number?
if($i = array_search( $number, $array)) return $i;
#add the number to the array
$array[] = $number;
#sort and refind the number
sort($array);
$i = array_search($number, $array);
#check if there is a number above it
if($i && isset($array[$i+1])) return $array[$i+1];
//alternatively you could return the number itself here, or below it depending on your requirements
return null;
}
для запуска echo closest($array, 38);
Здесь используется меньшая функция, которая также вернет ближайшее значение. Полезно, если вы не хотите сортировать массив (чтобы сохранить ключи).
function closest($array, $number) {
//does an exact match exist?
if ($i=array_search($number, $array)) return $i;
//find closest
foreach ($array as $match) {
$diff = abs($number-$match); //get absolute value of difference
if (!isset($closeness) || (isset($closeness) && $closeness>$diff)) {
$closeness = $diff;
$closest = $match;
}
}
return $closest;
}
Проведите линейное сканирование каждого номера и обновите две переменные, и вы сделаете это.
Код Python (производительность O (N), я не думаю, что можно бить O (N)):
def closestNum(numArray, findNum):
diff = infinity # replace with actual infinity value
closestNum = infinity # can be set to any value
for num in numArray:
if((num - findNum) > 0 and (num - findNum) < diff):
diff = num - findNum
closestNum = num
return closestNum
При необходимости добавьте нулевые проверки.
Если вы действительно хотите, чтобы значение, "ближайшее" на расстоянии, даже если оно меньшее значение, попробуйте это, что @Jason получает большую часть кредита.
Представьте себе сценарий, когда вы хотите, чтобы самое близкое число до 38.9:
$array = array(37.5, 38.5, 39.5);
Большинство решений здесь дадут вам 39,5, когда 38,5 намного ближе. Это решение будет принимать только самое высокое значение, если то, что вы ищете, находится в точной середине между двумя числами в массиве:
function nearest_value($value, $array) {
if (array_search($value, $array)) {
return $value;
} else {
$array[] = $value;
sort($array);
$key = array_search($value, $array);
if ($key == 0) { return $array[$key+1]; }
if ($key == sizeof($array)-1) { return $array[$key-1]; }
$dist_to_ceil = $array[$key+1]-$value;
$dist_to_floor = $value-$array[$key-1];
if ($dist_to_ceil <= $dist_to_floor) {
return $array[$key+1];
} else {
return $array[$key-1];
}
}
}
То, что ему не хватает в элегантности, это компенсируется точностью. Опять же, спасибо @Jason.
Попробуйте эту простую функцию PHP:
<?php
function nearest($number, $numbers) {
$output = FALSE;
$number = intval($number);
if (is_array($numbers) && count($numbers) >= 1) {
$NDat = array();
foreach ($numbers as $n)
$NDat[abs($number - $n)] = $n;
ksort($NDat);
$NDat = array_values($NDat);
$output = $NDat[0];
}
return $output;
}
echo nearest(90, array(0, 50, 89, 150, 200, 250));
?>
Я сделал для этого более короткую функцию:
function nearestNumber($num, $array) {
if(!in_array($num, $array)) $array[] = $num;
sort($array);
$idx = array_search($num, $array);
if(($array[$idx] -$array[$idx-1]) >= ($array[$idx+1] -$array[$idx])) return $array[$idx+1];
else return $array[$idx-1];
}
Отлично работает в моем случае: $array = array(128,160,192,224,256,320); $num = 203
:)
Принимая самое ближайшее число, и если там будет такое же расстояние между двумя номерами (например, 208 для моего примера), используется следующий самый высокий номер.
+1 Джейсону.
Моя реализация ниже, но не так, как быстрая
$array = array(1,2,4,5,7,8,9);
function closest($array, $number) {
$array = array_flip($array);
if(array_key_exists($number, $array)) return $number;
$array[$number] = true;
sort($array);
$rendered = array_slice($array, $number, 2, true);
$rendered = array_keys($rendered);
if(array_key_exists(1, $rendered)) return $rendered[1];
return false;
}
print_r(closest($array, 3));
Вы можете использовать array_reduce
для этого, что делает его более функциональным, стиль программирования:
function closest($needle, $haystack) {
return array_reduce($haystack, function($a, $b) use ($needle) {
return abs($needle-$a) < abs($needle-$b) ? $a : $b;
});
}
В остальном это следует тому же принципу, что и другие решения O (n).
Вот мое решение.
$array=array(10,56,78,17,30);
$num=65;
$diff=$num;
$min=$num;
foreach($array as $a){
if( abs($a-$num)< $diff ){
$diff=abs($a-$num);
$min=$a;
}
}
echo $min;