0

I have one input number range 20 to 60. And i have predefined number ranges as follows :

  • 18 to 24
  • 25 to 34
  • 35 to 44
  • 45 to 54
  • 55 to 64
  • 65+

I want to get the predefined number ranges which is between the input number range. For the range 20 to 60 I would like to get 18 to 24, 25 to 34, 35 to 44, 45 to 54, 55 to 64 .

Below is the code which tried to achieve this :

     $min_age = 20; $max_age = 60; $age_range = [];
     if(in_array($min_age, range(18, 24)) || in_array($max_age, range(18, 24))) {
         $age_range[] = [ 'type' => AgeRangeType::AGE_RANGE_18_24 ];
     } 
     
     if(in_array($min_age, range(25, 34)) || in_array($max_age, range(25, 34))) {
         $age_range[] = [ 'type' => AgeRangeType::AGE_RANGE_25_34 ];
     }
     if(in_array($min_age, range(35, 44)) || in_array($max_age, range(35, 44))) {
         $age_range[] = [ 'type' => AgeRangeType::AGE_RANGE_35_44 ];
     }
     if(in_array($min_age, range(45, 54)) || in_array($max_age, range(45, 54))) {
         $age_range[] = [ 'type' => AgeRangeType::AGE_RANGE_45_54 ];
     }
     if(in_array($min_age, range(55, 64)) || in_array($max_age, range(55, 64))) {
         $age_range[] = [ 'type' => AgeRangeType::AGE_RANGE_55_64 ];
     }
     if(in_array($min_age, range(65, 65)) || in_array($max_age, range(65, 65))) {
         $age_range[] = [ 'type' => AgeRangeType::AGE_RANGE_65_UP ];
     }

But i'm not getting the proper result.

VinoCoder
  • 1,133
  • 5
  • 22
  • 45
  • `20` is not between `25` and `34`, and neither is `60`. You need to cover the cases where your min and max completely "encompass" the predefined range, as well. – CBroe Apr 20 '22 at 07:44
  • @Cbroe It could be the other way around. For `18 to 24` the section `20 to 24` lies within the range `20 to 60`. I'm not sure what is wanted here. – KIKO Software Apr 20 '22 at 07:45
  • 1
    If you're not getting the proper result, given the code in your question, you should be very explicit about the results you do want to get. From what I can see in your question only the range `65+` needs to be discounted, because there's no overlap with the `20 to 60` range, is that correct? – KIKO Software Apr 20 '22 at 07:47
  • 1
    It would be nice to see the definition of `AgeRangeType`. – KIKO Software Apr 20 '22 at 07:49
  • FYI - there's a faster way to find out if two ranges overlap than generating (`range()`) an array full of numbers - [What's the most efficient way to test if two ranges overlap?](https://stackoverflow.com/questions/3269434/whats-the-most-efficient-way-to-test-if-two-ranges-overlap) – Hendrik Apr 20 '22 at 07:53
  • @CBroe Yes I would like to get the predefined range which has even one number match with the input range – VinoCoder Apr 20 '22 at 07:54
  • make one `allowed array` from 20-60 and do `array_intersect()` with the respective `age_range`. If the result is not empty it has a match. Saves a lot of `in_array()` and `range()` creating. – Michel Apr 20 '22 at 07:55
  • @KIKOSoftware `AgeRangeType` is a Enum reference from google ads api. Which returns some id. I just wanted all the ids to be in one array – VinoCoder Apr 20 '22 at 07:57
  • Ah, I found it: [AgeRangeType](https://developers.google.com/google-ads/api/reference/rpc/v7/AgeRangeTypeEnum.AgeRangeType#age_range_18_24). – KIKO Software Apr 20 '22 at 07:58

3 Answers3

2

I created this function:

function getGoogleAgeRanges($minumumAge, $maximumAge)
{
    $ageRanges = [AgeRangeType::AGE_RANGE_18_24 => ['min' => 18, 'max' => 24],
                  AgeRangeType::AGE_RANGE_25_34 => ['min' => 25, 'max' => 34],
                  AgeRangeType::AGE_RANGE_35_44 => ['min' => 35, 'max' => 44],
                  AgeRangeType::AGE_RANGE_45_54 => ['min' => 45, 'max' => 54],
                  AgeRangeType::AGE_RANGE_55_64 => ['min' => 55, 'max' => 64],
                  AgeRangeType::AGE_RANGE_65_UP => ['min' => 65, 'max' => 135]];
   $result = [];
   foreach ($ageRanges as $googleRangeEnum => $ageRange) {
       if ($ageRange['max'] >= $minumumAge && 
           $ageRange['min'] <= $maximumAge) {
           $result[] = $googleRangeEnum;
       }
       elseif (!empty($result)) break;
   }
   return $result;
}   
          
print_r(getGoogleAgeRanges(20, 60));     

When executed it returns all age ranges except the 65+ one. It is quite self explanatory: I created an array with data to work with, then loop through the array to gather what is needed, and return it.

KIKO Software
  • 15,283
  • 3
  • 18
  • 33
  • If the ranges are ordered then one micro-optimization would be to return early when we find the first non matching range. – Hendrik Apr 20 '22 at 08:17
  • @Hendrik How about: `elseif (!empty($result)) break;`? It's, on average, probably a bit faster, but there's not much in it. – KIKO Software Apr 20 '22 at 08:21
  • 1
    Looks good to me. Probably not especially needed here, but could be useful for general solution with lots of ordered ranges. – Hendrik Apr 20 '22 at 08:23
0

Just changed a code little bit and it worked as i expected :

$min_age = 20;
$max_age = 60;
$age_range = [];
        
if(in_array(18, range($min_age, $max_age)) || in_array(24, range($min_age, $max_age))) {
      $age_range[] = [ 'type' => AgeRangeType::AGE_RANGE_18_24 ];
}       
if(in_array(25, range($min_age, $max_age)) || in_array(34, range($min_age, $max_age))) {
      $age_range[] = [ 'type' => AgeRangeType::AGE_RANGE_25_34 ];
}
if(in_array(35, range($min_age, $max_age)) || in_array(44, range($min_age, $max_age))) {
      $age_range[] = [ 'type' => AgeRangeType::AGE_RANGE_35_44 ];
}
if(in_array(45, range($min_age, $max_age)) || in_array(54, range($min_age, $max_age))) {
      $age_range[] = [ 'type' => AgeRangeType::AGE_RANGE_45_54 ];
}
if(in_array(55, range($min_age, $max_age)) || in_array(64, range($min_age, $max_age))) {
      $age_range[] = [ 'type' => AgeRangeType::AGE_RANGE_55_64 ];
}
if($min_age >= 65 || $max_age >= 65) {
      $age_range[] = [ 'type' => AgeRangeType::AGE_RANGE_65_UP ];
}
VinoCoder
  • 1,133
  • 5
  • 22
  • 45
0

Admittedly, the bones of my answer are based on KIKO's answer, but I made some PSR-12 compliant choices, some personal code styling adjustments, and adjusted the way the enum names were accessed (so that they work). I have somewhat of a bias toward using array destructuring in a foreach loop because I like the avoidance of array syntax in the conditional expression -- I feel it just reads a little cleaner. Because $result is guaranteed to exist, calling !empty() is unnecessary -- a truthy check will tell you if the array is non-empty. Read here about using object property property syntax to access the enum's string value. Because the whitelist of enum cases will not be changed, it is sensible to declare it as a constant -- which enjoys a global scope (see the alternative approach link).

Code: (Demo) (An alternative approach)

enum AgeRangeType
{
    case UNSPECIFIED;            // Not specified.
    case UNKNOWN;                // Used for return value only. Represents value unknown in this version.
    case AGE_RANGE_18_24;        // Between 18 and 24 years old.
    case AGE_RANGE_25_34;        // Between 25 and 34 years old.
    case AGE_RANGE_35_44;        // Between 35 and 44 years old.
    case AGE_RANGE_45_54;        // Between 45 and 54 years old.
    case AGE_RANGE_55_64;        // Between 55 and 64 years old.
    case AGE_RANGE_65_UP;        // 65 years old and beyond.
    case AGE_RANGE_UNDETERMINED; // Undetermined age range.
}

$ageRanges = [
    AgeRangeType::AGE_RANGE_18_24->name => ['min' => 18, 'max' => 24],
    AgeRangeType::AGE_RANGE_25_34->name => ['min' => 25, 'max' => 34],
    AgeRangeType::AGE_RANGE_35_44->name => ['min' => 35, 'max' => 44],
    AgeRangeType::AGE_RANGE_45_54->name => ['min' => 45, 'max' => 54],
    AgeRangeType::AGE_RANGE_55_64->name => ['min' => 55, 'max' => 64],
    AgeRangeType::AGE_RANGE_65_UP->name => ['min' => 65, 'max' => 135]
];

$min_age = 20;
$max_age = 60;

$result = [];
foreach ($ageRanges as $enum => ['min' => $min, 'max' => $max]) {
   if ($max >= $min_age && $min <= $max_age) {
       $result[] = $enum;
   } elseif ($result) {
       break;
   }
}

var_export($result);

Output:

array (
  0 => 'AGE_RANGE_18_24',
  1 => 'AGE_RANGE_25_34',
  2 => 'AGE_RANGE_35_44',
  3 => 'AGE_RANGE_45_54',
  4 => 'AGE_RANGE_55_64',
)
mickmackusa
  • 43,625
  • 12
  • 83
  • 136