1

What's the best way of searching an array for a number within a range? e.g. between 1000 and 1500.

<?php
$numbers = array(1105,2140,3170);

$needle = **value between 1000 and 1500**;

if (in_array($needle, $numbers)) {
  echo "Match found";
} else {
  echo "Match not found";
}
?>

In this case, this would return 'Match found' as 1105 is between 1000 and 1500.

Can I set a range for the $needle variable?

AbraCadaver
  • 78,200
  • 7
  • 66
  • 87
traummaschine
  • 439
  • 8
  • 18

3 Answers3

2

What's the best way of searching an array for a number within a range. To answer this, there are 2 approaches as mentioned below:

Approach #1:

You can use a simple foreach loop to get all values from your unordered data which lie in the range.

<?php

$numbers = array(1105,2140,3170);

$start = 1000;
$end = 1500;

$result = [];

foreach($numbers as $num){
    if($num >= $start && $num <= $end) $result[] = $num;
}

print_r($result);

Demo: https://3v4l.org/D1Rfu

Approach #2:(recommended for future lookups)

You can sort your data and use binary search to get the starting point of where your numbers start falling in the range of start and end for faster lookups. Then, you can just look from that index till the index you get a higher number or reach the end of the array.

<?php

$numbers = array(1105,2140,3170,1000,1500,1501);

$start = 1000;
$end  = 1500;
$start_index = -1;

sort($numbers);

$low = 0; $high = count($numbers) - 1;

while($low <= $high){
    $mid = intval(($low + $high) / 2);
    if($numbers[$mid] > $end){
        $high = $mid - 1;
    }else if($numbers[$mid] < $start){
        $low = $mid + 1;
    }else{
        $start_index = $mid;
        $high = $mid - 1;
    }
}

$result = [];
for($i = $start_index; $i < count($numbers); ++$i){
    if($numbers[$i] > $end) break;
    $result[] = $numbers[$i];
}

print_r($result);

Demo: https://3v4l.org/WcgXv

nice_dev
  • 17,053
  • 2
  • 21
  • 35
  • @revo Thanks. Yes, first approach is the best, however if there are frequent lookups for different ranges, approach 2 is better. – nice_dev Feb 14 '20 at 18:46
1

Yes, you can create a range and use it as the "needle", but not using in_array. You can create a range and compute the intersection of the numbers array. To just check for any match:

$numbers = array(1105, 2140, 3170);
$needle  = range(1000, 1500);

if (array_intersect($numbers, $needle)) {
  echo "Match found";
} else {
  echo "Match not found";
}

Or to get the possible match(es):

$numbers = array(1105, 2140, 3170);
$needle  = range(1000, 1500);
$result  = array_intersect($numbers, $needle);

Or you can filter out the ones not in the range:

$numbers = array(1105, 2140, 3170);
$min = 1000;
$max = 1500;
$result  = array_filter($numbers, function($v) use($min, $max) {
                                     return $v >= $min && $v <= $max;
                                 });

You will get an empty array if there are no matches in either case. Also, you don't state what you want if there is more than one, but you'll get an array in either case so you could use current for one or min and/or max instead:

$one = current(array_intersect($numbers, $needle));
$min = min(array_intersect($numbers, $needle));
$max = max(array_intersect($numbers, $needle));
AbraCadaver
  • 78,200
  • 7
  • 66
  • 87
-1

There is no built-in function for these purpose. So create a function that will help you.

function searchOnRange(array $stack, $min=0, $max=0)
{
    // Loop through each value of array
    foreach($stack as $value){
        // CHeck value is between the given range
        if(($value >= $min) && ($value <= $max)){
            echo "Match found - ".$value;
        } else {
            echo "Match not found - ".$value;
        }
    }
}

$numbers = array(1105,2140,3170);
searchOnRange($numbers, 1000, 1500);
mail2bapi
  • 1,547
  • 1
  • 12
  • 18