Найти число, которое больше или равно N в массиве - PullRequest
20 голосов
/ 27 мая 2011

Если у меня есть массив PHP:

$array

со значениями:

45,41,40,39,37,31

И у меня есть переменная:

$number = 38;

Как я могу вернуть значение?:

39

Потому что это самое близкое значение к 38 (считая) в массиве?

С уважением,

1017 * Тэйлора *

Ответы [ 11 ]

24 голосов
/ 27 мая 2011
<?php
function closest($array, $number) {

    sort($array);
    foreach ($array as $a) {
        if ($a >= $number) return $a;
    }
    return end($array); // or return NULL;
}
?>
10 голосов
/ 27 мая 2011

Это высокоуровневый процесс для получения желаемых результатов и работы с любыми данными массива:

  • Фильтрация массива по значениям , большим или равным целии затем выберите самое низкое оставшееся значение.Это «лучшее» значение (которое может быть «ничем», если все значения были меньше) - это O(n)
  • В качестве альтернативы, сначала отсортируйте данные и посмотрите ниже - это O(n lg n)(с надеждой)

Теперь, если предположить, что массив отсортирован ASCENDING, этот подход будет работать:

  • Выполните цикл по массиву и найдите first элемент, который больше или равен целевому элементу - это O(n)

И если для массива задано значение DESCENDING (как в сообщении), выполните действия, указанные выше, но либо:

  • Итерация в обратном направлении - это O(n)
  • Сортировать сначала по возрастанию (см. Ответ Фардджада) - это O(n lg n) (надеюсь)
  • Итерация вперед, но сохранение значения «назад» (чтобы помнить «следующее наивысшее», если точное значение было пропущено) - это O(n)

Счастливое кодирование.

7 голосов
/ 27 мая 2011

РЕДАКТИРОВАТЬ опечатка в 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);

4 голосов
/ 10 сентября 2013

Вот небольшая функция, которая также будет возвращать ближайшее значение.Полезно, если вы не хотите сортировать массив (чтобы сохранить ключи).

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;
}
2 голосов
/ 27 мая 2011

Выполните линейное сканирование каждого числа и обновите две переменные, и все будет готово.

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

Пожалуйста, добавьте пустые проверки в зависимости от ситуации.

1 голос
/ 15 февраля 2013

Если вы действительно хотите, чтобы значение было «самым близким» по расстоянию, даже если оно меньше, попробуйте это, за что @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.

0 голосов
/ 27 ноября 2016

Вы можете использовать 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) решений.

0 голосов
/ 11 мая 2015

+ 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));
0 голосов
/ 13 февраля 2015

Я сделал для этого более короткую функцию:

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 в моем примере), используется следующий наибольший номер.

0 голосов
/ 20 июня 2014

Попробуйте эту простую функцию 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));
?>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...