Intereting Posts
Руководство по внедрению сервера Oauth2 PHP с использованием библиотеки Использовать utf8 или нет – проблема с кодировкой символов MySQL и PHP CakePhp: Cake Email AfterSend event формат отображения даты как сохранить профиль пользователя pic в facebook с помощью php Mac / OSx – изменить версию PHP, которая вызывает вызов bash Ошибка импорта gnupg в PHP? WooCommerce получить заказ всего Как предотвратить загрузку любого вредоносного файла на моем сервере? (проверить тип файла)? Как вызвать родительские методы PHP из унаследованного метода? Добавить текст в строку с использованием регулярного выражения (preg_replace: php) с ограниченными словами Обновление значения узла с помощью простого XML-кода PHP и xpath не работает Отправка электронной почты через почту PHP медленная Как добавить JavaScript динамически в Opencart? Полоса прокрутки автоматически скрыта, если я не изменю размер страницы

Как определить два числа, которые ближе друг к другу в массиве

У меня есть этот массив:

$arr = array (20, 1, 5, 10, 7, 16); 

Я хотел бы получить 5 и 7 . Потому что они ближе друг к другу, чем другие предметы. Другими словами, разница между ними – самое низкое число:

 7 - 5 = 2 // 2 is lowest number as the difference between all array's items 

Как я могу это сделать?


 $keep = $arr[0]; $diff = $arr[1] - $arr[0]; foreach ($arr as $item) { if ( ($keep - $item) < $diff && $keep != $item ) { $diff = $item; } } 

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

Solutions Collecting From Web of "Как определить два числа, которые ближе друг к другу в массиве"

объяснение

Таким образом, чтобы получить два числа в массиве, которые наиболее близки друг к другу, вам нужно сравнить каждое значение друг с другом. Но вам не нужно сравнивать их с собой и с предыдущими, которые вы уже сравнили.

Чтобы рассчитать, сколько сравнений вы должны сделать, вы можете использовать биномиальный коэффициент :

 (n) n! (k) → ───────────── k! * (n - k)! 

Где n – общее количество элементов и k, сколько вы выбираете

И в вашем примере это означало бы:

 n = 6 //Array elements k = 2 //Two values which you compare 6! 720 ───────────── → ───────────── = 15 comparison 2! * (6 - 2)! 2 * 24 

Визуализация

 20 , 1 , 5 , 10 , 7 , 16 //Array values ↓ ↑ ↑ ↑ ↑ ↑ └────┴───┴───┴────┴───┘ //20 compared to all values, except itself ↓ ↑ ↑ ↑ ↑ └───┴───┴────┴───┘ //1 compared to all values, except itself + [20] ↓ ↑ ↑ ↑ └───┴────┴───┘ //5 compared to all values, except itself + [20, 1] ↓ ↑ ↑ └────┴───┘ //10 compared to all values, except itself + [20, 1, 5] ↓ ↑ └───┘ //7 compared to all values, except itself + [20, 1, 5, 10] //16 compared to all values, except itself + [20, 1, 5, 10, 7] 

Теперь, чтобы сделать это в коде, нам нужно 2 цикла, чтобы перебрать весь массив для каждого значения первого цикла. Но, как мы уже говорили, мы можем игнорировать само значение и предыдущие значения, поэтому для этого мы используем 2 для циклов и устанавливаем ключ для внутреннего цикла как внешний ключ + 1.

 for($key = 0, $length = count($arr); $key < $length; $key++){ for( $innerKey = $key + 1 ; $innerKey < $length; $innerKey++){ //↑ Skipping the previous values and the value itself } } 

Во внутреннем цикле нам просто нужно получить доступ к текущему значению внешнего цикла и получить разницу по сравнению со значением внутреннего цикла. То, что это также работает с отрицательными числами, мы просто переносим на вызов abs() чтобы сделать разницу всегда положительной.

Затем мы просто проверяем, меньше ли разница, чем самая маленькая разница, которую мы уже нашли, сохраненная в $nearest . (Мы инициализировали $nearest к разнице наибольшего и наименьшего значения массива + 1):

 if( ($diff = abs($arr[$keys[$key]] - $arr[$keys[$innerKey]])) < $nearest) 

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

 $result = [$arr[$keys[$key]], $arr[$keys[$innerKey]]]; $nearest = $diff; 

Код

 <?php $arr = [20, 1, 5, 10, 7, 16]; $keys = array_keys($arr); $nearest = max($arr) - min($arr) + 1; $result = []; for($key = 0, $length = count($arr); $key < $length; $key++){ for($innerKey = $key + 1; $innerKey < $length; $innerKey++){ if( ($diff = abs($arr[$keys[$key]] - $arr[$keys[$innerKey]])) < $nearest){ $result = [$arr[$keys[$key]], $arr[$keys[$innerKey]]]; $nearest = $diff; } } } print_r($result); ?> 

Вывод

 [5, 7] 

usort используется PHP usort , как примечание, которое реализовано с помощью quicksort.

$temp ==> Временный массив для хранения двух значений и их различий при циклизации
$temp = [arr[$i] , arr[$j] , arr[$i]-arr[$j] ]

  $arr = array (20, 1, 5, 10, 7, 16); $temp=array(); for ($i = 0; $i < count($arr)-1; $i++) { $diff=0; for ($j = $i+1; ($j < count($arr) && $i!=$j); $j++) { $diff=abs($arr[$i]-$arr[$j]); //finding difference &taking absolute $temp[] = array($arr[$i],$arr[$j], $diff); } } usort($temp,function ($a, $b) { return $b[2] < $a[2]; });//sort `$temp[]` in ascending order according to the difference value list($x,$y,$d) = $temp[0]; //the first row of `$temp` contains values with the diff. is lowest //and the values is stored to `$x` & `$y` and there difference in `$d` echo "Related Values are $x and $y by $d"; 

Проверить результаты здесь http://ideone.com/pZ329m

За работой

  20 1 5 10 7 16 //inner loop ----------------------- | | | | | | $temp[]=[[20,1,19],[20,5,15],[20,10,10],...//$i=0 |// `20` is compared values from 1 onwards and the values and differences are stored in `$temp[]` |___|____|___|___|___| //(eg., $temp=[20,1,|20-1|]) //$j=1,2,3,4,5↓ | | | | | [1,5,4],[1,10,9],... //$i=1 | `1` is compared with values from 5 onwards |____|___|___|___| //$j=2,3,4,5 ↓outer loop | | | | [5,10,5],[5,7,2],... //$i=2 | `5` is compared with values from 10 onwards |___|___|___| //$j=3,4,5 ↓ | | | [10,7,3],[10,16,6] //$i=3 | `10` is compared with values from 7 onwards |___|___| //$j=4,5 ↓ | | [7,16,9]] //$i=4 |`7` is compared with final value `16` |___| //$j=5 ↓ 

Получив $temp[] , он сортируется в порядке возрастания в соответствии с differences .
Тогда первая строка $temp[] дает наш желаемый результат.

Что внутри $temp[]

  Array ( [0] => Array ( [0] => 7 [1] => 5 [2] => 2 ) [1] => Array ( [0] => 7 [1] => 10 [2] => 3 ) [2] => Array ( [0] => 16 [1] => 20 [2] => 4 ) [3] => Array ( [0] => 5 [1] => 1 [2] => 4 ) [4] => Array ( [0] => 10 [1] => 5 [2] => 5 ) [5] => Array ( [0] => 16 [1] => 10 [2] => 6 ) [6] => Array ( [0] => 7 [1] => 1 [2] => 6 ) [7] => Array ( [0] => 16 [1] => 7 [2] => 9 ) [8] => Array ( [0] => 10 [1] => 1 [2] => 9 ) [9] => Array ( [0] => 10 [1] => 20 [2] => 10 ) [10] => Array ( [0] => 16 [1] => 5 [2] => 11 ) [11] => Array ( [0] => 7 [1] => 20 [2] => 13 ) [12] => Array ( [0] => 5 [1] => 20 [2] => 15 ) [13] => Array ( [0] => 16 [1] => 1 [2] => 15 ) [14] => Array ( [0] => 1 [1] => 20 [2] => 19 ) ) 

Поскольку я комментирую использование цикла 2 и условия, я сделал то же самое. Просто проверьте это и дайте мне знать.

 $arr = array (20, 1, 5, 10, 7, 16); $c = count($arr); $ld = max($arr); for($i = 0; $i < $c; $i++){ for($j = $i+1; $j < $c; $j++){ $abs = abs($arr[$i]-$arr[$j]); if($abs < $ld) $ld = $abs; } } echo $ld; //2 

если вам нужно знать, какое из двух значений имеет разницу, то это возможно, просто сохраните их внутри условия if.

Ну, быстрая и грязная … две петли, одно условие

 //$arr = array (20, 1, 5, 10, 7, 16); gives 5 and 7 $arr = array (-32,-15,4,6,-14,613,4,63,6,4); $diff = INF; foreach ($arr as $item0) { foreach ($arr as $item1) { $localdiff = abs($item0 - $item1); if ( $localdiff > 0 && $localdiff < $diff ) { $diff = $localdiff; $keep0 = $item0; $keep1 = $item1; } } } echo "Smallest distance was $diff, between $keep0 and $keep1"; 

Проверьте это на http://ideone.com/WdWOcb

использовать это

  $arr = array (20, 1, 5, 10, 7, 16); $temp = array(); foreach ($arr as $item1) { foreach ($arr as $item2) { $aV = abs($item1-$item2); if(!in_array($aV, $temp) && $aV!=0) $temp[$item1."-".$item2] =$aV; } } $closest = array_keys($temp,min($temp)); list($first,$explode,$second) = $closest[0]; print "The two closest numbers are " . $first . " and " . $second; 
 $arr = array(20, 1, 5, 10, 7, 16); $min = max($arr); $closest = array(); foreach ($arr as $i) { foreach ($arr as $j) { if ($i != $j) { $diff = abs($i - $j); if ($min > $diff) { $min = $diff; $closest[0] = $i; $closest[1] = $j; } } } } print "The two closest numbers are " . $closest[0] . " and " . $closest[1]; 

Непонятно, что происходит в этой ситуации:

 $arr = array( 14, 20, 1, 5, 10, 7, 16 ); 

В приведенном выше случае у вас есть две пары с 2 как разница (7-5, 16-14). Следующий код возвращает все относительные значения.

Мы выполняем стандартные два вложенных цикла для сравнения всех элементов (основной цикл, исключающий последний элемент, вложенный цикл, начинающийся с основного индекса +1), тогда, если разница между текущими значениями ниже, чем ранее полученная разница, мы ее заменяем; в противном случае, если разница равна предыдущей разнице, добавим новую пару:

 $result = array( 'sum' => INF, 'values'=> array() ); for( $i=0; $i < count( $arr )-1; $i++ ) { for( $j = $i+1; $j < count( $arr ); $j++ ) { $dif = abs( $arr[$i] - $arr[$j] ); if( $dif < $result['sum'] ) { $result = array( 'sum' => $dif, 'values'=> array( array( $arr[$i], $arr[$j] ) ) ); } elseif( $dif == $result['sum'] ) { $result['values'][] = array( $arr[$i], $arr[$j] ); } } } 

На этом этапе, для образца массива выше, вы получите следующий результат:

 Array ( [sum] => 2 [values] => Array ( [0] => Array ( [0] => 14 [1] => 16 ) [1] => Array ( [0] => 5 [1] => 7 ) ) ) 

Если вас интересует все значение, просто вы можете найти их в $result['values'] . В противном случае, если вы хотите (т. usort ) Минимальные значения (5 и 7), вы можете usort -it:

 usort( $result['values'], function( $a, $b ) { return min($a)-min($b); } ); 

и используйте $result['values'][0] :

 [0] => Array ( [0] => 5 [1] => 7 ) 

попробуй это

 $arr = array (20, 1, 5, 10, 7, 16); arsort($arr, SORT_NUMERIC); $arr = array_values( $arr ); $min = 0; foreach( $arr as $index => $number ){ if( isset($arr[$index+1]) ){ $diff = abs( $number - $arr[$index+1] ); if( $diff < $min || $min == 0 ){ $min = $diff; $result = array( $number, $arr[$index+1] ); } } } print_r( $result );