Home > Enterprise >  Avoid loop in PHP function and adhere to principles of functional programming
Avoid loop in PHP function and adhere to principles of functional programming

Time:08-24

I would like to solve the following problem while following the principles of functional programming. I have an array with "date To" ranges with these values: [30,60,90,120,360] and this array represents days intervals:

Index : interval
- - - - - - - - - 
0 : 0-30 
1 : 31-60
2: 61-90
4 : 91–360
5 : 361 – infinity

Now I have a value of x , let's say 75 days. Using functional programming, how do I find out (according to the days intervals defined in the array) that this value belongs to an interval with index 2?

I solved this algorithm in function with loop, but I know, that I should use recursive call instead. I don't know how.

Here is my code:

function indexByDateRange(array $intervalRange, int $days) {
    foreach ($intervalRange as $i=>$value) {
        if ($days <= $value) {
            return $i;
        }
    }
    return count($intervalRange);
}

$index = indexByDateRange(array(30,60,90,120,360), 73); // 73 is between 61 and 90 , so should return index = 2

$index = indexByDateRange(array(30,60,90,120,360), 4; // 4 is smaller then 30 , so should return index = 0

Any suggestion how to rewrite the indexByDateRange function so it will comply with Functional Programming principles?

CodePudding user response:

Define a function that takes an array and a callback function. This will use a loop like the one that you wrote to find the first array element that satisfies the function. Then you can call that in your functional programming style.

function array_search_callback($callback, $array) {
    foreach ($array as $i => $el) {
        if (($callback)($el)) {
            return $i;
        }
    }
    return count($array);
}

$intervalRange = [30,60,90,120,360];
$days = 73;
$index = array_search_callback(function($value) use ($days) {
    return $days <= $value;
}, $intervalRange);

CodePudding user response:

just quick sample how you can do it in more functional way:

function indexByDateRange(array $intervalRange, int $days) {
    return array_key_first(array_filter(
        $intervalRange,
        function($v) use ($days) {
            return $days <= $v;
        })) ?? count($intervalRange);
}

CodePudding user response:

I don't see any compelling reason to use recursion for such a basic, linear value searching function.

Simply find the key of the element which is the first to meet or exceed the target value. A continual break or return will ensure best performance.

Code: (Demo)

function greatestIndexWhereValueLessThan($haystack, $needle) {
    foreach ($haystack as $key => $value) {
        if ($value >= $needle) {
            break;
        }
    }
    return $key ?? null;
}

echo greatestIndexWhereValueLessThan([30, 60, 90, 120, 360], 73); // 2
echo "\n";
echo greatestIndexWhereValueLessThan([30, 60, 90, 120, 360], 4);  // 0
  • Related