Search code examples
phparraysnumbersrangetext-parsing

Expand array of numbers and hyphenated number ranges to array of integers


I'm trying to normalize/expand/hydrate/translate a string of numbers as well as hyphen-separated numbers (as range expressions) so that it becomes an array of integer values.

Sample input:

$array = ["1","2","5-10","15-20"];

should become :

$array = [1,2,5,6,7,8,9,10,15,16,17,18,19,20];

The algorithm I'm working on is:

//get the array values with a range in it :
$rangeArray = preg_grep('[-]',$array);

This will contain ["5-10", "16-20"]; Then :

foreach($rangeArray as $index=>$value){
    $rangeVal = explode('-',$value);
    $convertedArray = range($rangeVal[0],$rangeVal[1]);
}

The converted array will now contain ["5","6","7","8","9","10"];

The problem I now face is that, how do I pop out the value "5-10" in the original array, and insert the values in the $convertedArray, so that I will have the value:

$array = ["1","2",**"5","6","7","8","9","10"**,"16-20"];

How do I insert one or more values in place of the range string? Or is there a cleaner way to convert an array of both numbers and range values to array of properly sequenced numbers?


Solution

  • Here you go. I tried to minimize the code as much as i can.

    Consider the initial array below,

    $array = ["1","2","5-10","15-20"];
    

    If you want to create a new array out of it instead $array, change below the first occurance of $array to any name you want,

    $array = call_user_func_array('array_merge', array_map(function($value) {
                if(1 == count($explode = explode('-', $value, 2))) {
                    return [(int)$value];
                }
                return range((int)$explode[0], (int)$explode[1]);
            }, $array));
    

    Now, the $array becomes,

    $array = [1,2,5,6,7,8,9,10,15,16,17,18,19,20];
    

    Notes:

    • Casts every transformed member to integer
    • If 15-20-25 is provided, takes 15-20 into consideration and ignores the rest
    • If 15a-20b is provided, treated as 15-20, this is result of casing to integer after exploded with -, 15a becomes 15
    • Casts the array keys to numeric ascending order starting from 0
    • New array is only sorted if given array is in ascending order of single members and range members combined