Home > Back-end >  How to get a specific range within an array in PHP?
How to get a specific range within an array in PHP?

Time:09-29

Given a simple array of 10 delicious fruits:

$fruits = [
    'apple',
    'kumquat',
    'pomegranate',
    'jujube',
    'plum',
    'passon_fruit',
    'pineapple',
    'strawberry',
    'raspberry',
    'grapefruit',
];

I would like to retrieve a specific range/spread, using a given key as a reference. The range should always be the exact length, so the starting point might differ.

Easiest example from the middle: key is 4 (plum) with length 5 would result in:

$result = [
    'pomegranate',
    'jujube',
    'plum', // reference
    'passon_fruit',
    'pineapple',
];

However, with key 1 (kumquat), we only have item 0 left and need 4 more at the end:

$result = [
    'apple',
    'kumquat', // reference
    'pomegranate',
    'jujube',
    'plum',
];

Same goes for key 8 (raspberry), which needs more items from the beginning of the array:

$result = [
    'passon_fruit',
    'pineapple',
    'strawberry',
    'raspberry', // reference
    'grapefruit',
];

Edit

As suggested by @berend, here's what I tried. Please note that this does not fully do what I intended:

function getRange(array $array, int $ref, int $spread)
{
    $min = $ref - round(($spread / 2), 0, PHP_ROUND_HALF_DOWN);
    $max = $ref   round(($spread / 2), 0, PHP_ROUND_HALF_UP);

    if ($min < 0) {
        $max  = -$min;
        $min = 0;
    }
    
    if ($max > (count($array) - 1)) {
        $min = $min - ($max - count($array) - 1);
        
        // not enough items
        if ($min < 0) {
            $min = 0;
        }
    }

    return array_intersect_key($array, range($min, $max));
}

var_dump(getRange($fruits, 4, 5));
var_dump(getRange($fruits, 1, 5));
var_dump(getRange($fruits, 8, 5));

CodePudding user response:

I think it can be simplified by using array_slice instead. Then you don't need to get the max and make another array.

function getRange(array $array, int $ref, int $spread)
{

    // calculate an offset using your original method
    // use zero if you end up with a negative offset
    $min = max(0, $ref - round(($spread / 2), 0, PHP_ROUND_HALF_DOWN));

    // if the offset puts the range beyond the end of the array, recalculate 
    // it by subtracting the spread size from the array size
    // again, use zero if you end up with a negative offset
    if ($min   $spread > count($array)) {
        $min = max(0, count($array) - $spread);
    }

    return array_slice($array, $min, $spread);
}

If you need to preserve the keys, you can use the fourth argument of array_slice for that.


I think part of why yours isn't working is that you're using array_intersect_key, but in the range you're using as the second argument, the numbers you've calculated are the values, not the keys. There are a couple of other issues, but that looks like the main problem.

  • Related