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.