phparraysrangeslicepopulate

Populate a flat array of incremented integers with a limit and constraints to keep/ignore some values


I have array structure for 13 with range (1,13); it something like

array(1,2,3,4,5,6,7,8,9,10,11,12,13);

$slice = 2;
$ignore = 3;

I want array structure like array(3,4,5,8,9,10,13);

I tried with array_slice() function but I couldn't offset the value sequentially.

array_slice($array,2,13,true); is there a way to ignore the next 3 values and add slice to the next second until last array, any native function or key will be great.


Solution

  • To prioritize performance, minimize loops/cycles and function calls. Using a single for loop and no function calls is probably the most efficient approach but won't win any awards for being beautiful/intuitive code. (Demo)

    $limit = 13;
    $skip = 2;
    $keep = 3;
    $result = [];
    for (
        $x = 1 + $skip, $k = 1;
        $x <= $limit;
        $x += ($k++ % $keep ? 1 : 1 + $skip)
    ) {
        $result[] = $x;
    }
    var_export($result);
    

    Writing conditional continue statements means wasted/fruitless iterations -- ergo poorer performance, but maybe this is more comprehensible. (Demo)

    $limit = 13;
    $skip = 2;
    $keep = 3;
    $result = [];
    
    for ($x = 1; $x <= $limit; ++$x) {
        if (($x - 1) % ($skip + $keep) < $skip) {
            continue;
        }
        $result[] = $x;
    }
    var_export($result);
    

    A recursive approach can be written without declaring any variables beyond the callback signature. (Demo)

    function slice_recursive(array $array, int $skip, int $keep): array
    {
        if (!$array) {
            return $array;
        }
        return array_merge(
            array_slice(
                array_splice($array, 0, $skip + $keep),
                $skip
            ),
            slice_recursive($array, $skip, $keep)
        );
    }
    
    var_export(
        slice_recursive(range(1, 13), 2, 3)
    );
    

    A similar, non-recursive approach can be written too. In this script, the consumption of the input array has the effect of actually reducing the original array to an empty array. (Demo)

    $limit = 13;
    $skip = 2;
    $keep = 3;
    $result = [];
    
    $array = range(1, 13);
    while ($array) {
        array_push(
            $result,
            ...array_slice(
                array_splice($array, 0, $skip + $keep),
                $skip
            )
        );
    }
    var_export($result);
    

    There will be several more ways to satisfy the task requirements. Usually microoptimized performance is an unnecessary pursuit -- choose the script that you understand and can maintain.