Reputation: 749
$array = [
2 => 5,
8 => 3,
4 => 7,
11 => 1,
9 => 2,
];
I want the sum of values where the key fits in a specific period like 1-5
or 6-10
.
For my given input, I need this output:
[
'1-5' => 12, # 5 + 7
'6-10' => 5, # 3 + 2
]
Upvotes: -2
Views: 1778
Reputation: 48031
Considering that you might want to see all groups/ranges represented in the result and that some data might not qualify for any group, I've extended the sample data to show these considerations.
Use a conditionally broken nested loop with minimum and maximum numbers which will add amounts to respective groups/ranges.
array_map()
is used to establish a 0
value for all declared groups/ranges.
Code: (Demo)
$array = [
2 => 5,
4 => 1,
8 => 3,
0 => 17,
9 => 2,
11 => 67
];
$ranges = [
'1-5' => ['min' => 1, 'max' => 5],
'6-10' => ['min' => 6, 'max' => 10],
'1000-5000' => ['min' => 1000, 'max' => 5000],
];
$result = array_map(fn() => 0, $ranges);
foreach ($array as $num => $amount) {
foreach ($ranges as $rangeName => ['min' => $min, 'max' => $max]) {
if ($num >= $min && $num <= $max) {
$result[$rangeName] += $amount;
break;
}
}
}
var_export($result);
If you want to minimize iterations, you can remove elements after they qualify or get disqualified. This will "consume"/"destroy" the data in $array
. Demo
$result = [];
foreach ($ranges as $rangeName => ['min' => $min, 'max' => $max]) {
$result[$rangeName] = 0;
foreach ($array as $num => $amount) {
if ($num < $min) {
unset($array[$num]);
} elseif ($num <= $max) {
$result[$rangeName] += $amount;
unset($array[$num]);
}
}
}
var_export($result);
If your number ranges aren't gigantic, you can expand the hyphenated ranges into populated ranges, flip, filter, then sum for each range. The performance may not be awesome on "large" number ranges, so if efficiency is of high importance run some benchmarks. Here's a function-style script that mostly implements @rozsazoltan's advice but dynamically processes an array of hyphenated range strings. Demo
$ranges = ['1-5', '6-10', '1000-5000'];
var_export(
array_reduce(
$ranges,
fn($result, $range) => $result
+ [$range => array_sum(array_intersect_key($array, array_flip(range(...sscanf($range, '%d-%d')))))],
[]
)
);
Output (from any of above):
array (
'1-5' => 6,
'6-10' => 5,
'1000-5000' => 0,
)
Upvotes: 1
Reputation: 8835
You can extract the specific keys from an array, and then use array_sum
to add the extracted values.
$array = [
2 => 5,
4 => 1,
8 => 3,
9 => 2,
];
// the range() function gives the from-to values
$range = range(1, 5); // [0 => 1, 1 => 2, 2 => 3, 3 => 4, 4 => 5]
// move the 1-2-3-4-5 values to key
$rangeFlip = array_flip($range); // [1 => 0, 2 => 1, 3 => 2, 4 => 3, 5 => 4]
// search for the keys in the $array that match the keys of $rangeFlip
$rangeArray = array_intersect_key($array, $rangeFlip);
/*
[
2 => 5,
4 => 1,
]
*/
// sum the values of $rangeArray
$result = array_sum($rangeArray); // 5 + 1 = 6
range
- Creates an array containing a range of elements - PHP Docsarray_flip
- Exchanges all keys with their associated values in an array - PHP Docsarray_intersect_key
- Returns the intersection of arrays based on keys - PHP Docsarray_sum
- Calculates the sum of values in an array - PHP Docs$array = [
2 => 5,
4 => 1,
8 => 3,
9 => 2,
];
$range1 = range(1, 5); // [1, 2, 3, 4, 5]
$range2 = range(6, 10); // [6, 7, 8, 9, 10]
$result = [];
$result['1-5'] = array_sum(array_intersect_key($array, array_flip($range1)));
$result['6-10'] = array_sum(array_intersect_key($array, array_flip($range2)));
And then, from the previous logic, we can write our own function that takes the array containing the data and the range to specify which key values we are interested in, from-to.
$array = [
2 => 5,
4 => 1,
8 => 3,
9 => 2,
];
function array_sum_range($array, $range) {
return array_sum(array_intersect_key($array, array_flip($range)));
}
$result = [];
$result['1-5'] = array_sum_range($array, range(1, 5));
$result['6-10'] = array_sum_range($array, range(6, 10));
Upvotes: 0
Reputation: 24384
Try this code.. Not a rocket science..
function sumArray($array, $min, $max) {
$sum = 0;
foreach ($array as $k => $a) {
if ($k >= $min && $k <= $max) {
$sum += $a;
}
}
return $sum;
}
echo sumArray($array, 1, 5);
Upvotes: 4