Sum certain indice values in MultiDimensional Array - php

I have the following:
Array
(
[0] => Array
(
[department] => Central>ACME>BusDev
[Total_Staff] => 4
[Total_Resp] => 0
)
)
There are over 150 of these within the array.
I can easily sum, for example, Total_Staff and Total_Resp using something like:
foreach($arr as $num => $values) {
$sum_staff += $values[ 'Total_Staff' ];
$sum_resp += $values[ 'Total_Resp' ];
}
However what I need to do is sum only elements of the array, for example I need to sum Total_Staff and Total_resp that lies between indexes 0 and 7 or 12 and 58.
Not sure how to go about this.

Is this what you need
foreach($arr as $num => $values) {
if(($num >= 0 && $num <= 7) || ($num >= 12 && $num <= 58))
$sum += $values[ 'Total_Staff' ];
}

Using a for loop would be the way to solve this:
$start = 12;
$end = 58;
$sum_total_staff = 0;
$sum_total_resp = 0;
for( $i = $start; $i <= $end; $i++ ) {
$sum_total_staff += $arr[$i]["Total_Staff"];
$sum_total_resp += $arr[$i]["Total_Resp"];
}

Id say use these 2 function to slice & merge the arrays. It will get 8 arrays from which are between indexes 0-7 (with 0 and 7 included) and same with the second one. If you want without 0 and 7, it would be with arguments 1, 6, so array_slide($arr, 1, 6); and so on.
$new_arr1 = array_slice($arr, 0, 8);
$new_arr2 = array_slice($arr, 12, 47);
$arr = array_merge($new_arr1, $new_arr2);

Related

How To Reduce and Average Total PHP Array Elements To New Size

Whats the best solution to take an array with 100 elements (all numbers) and reduce the array size to a smaller number of elements averaging the in between/combined numbers into new. I do NOT mean slice or crop.
Example:
$array = [10,20,30,40,50,60];
$final_count = 3;
$new_array = array_slimmer($array, $final_count);
Output:
[15,35,55]
Here's a solution based on an existing answer about breaking an array into a set number of chunks:
$array = [11, 3, 45, 6, 61, 89, 22];
function array_slimmer(array $array, int $finalCount): array
{
// no work to be done if we're asking for equal or more than what the array holds
// same goes if we're asking for just one array or (nonsensical) less
if ($finalCount >= count($array) || $finalCount < 2) {
return $array;
}
return array_map(function (array $chunk) {
// rounded to two decimals, but you can modify to accommodate your needs
return round(array_sum($chunk) / count($chunk), 2);
}, custom_chunk($array, $finalCount));
}
// this function is from the linked answer
function custom_chunk($array, $maxrows) {
$size = sizeof($array);
$columns = ceil($size / $maxrows);
$fullrows = $size - ($columns - 1) * $maxrows;
for ($i = 0; $i < $maxrows; ++$i) {
$result[] = array_splice($array, 0, ($i < $fullrows ? $columns : $columns - 1));
}
return $result;
}
print_r(array_slimmer($array, 2));
print_r(array_slimmer($array, 3));
print_r(array_slimmer($array, 4));
This outputs:
Array ( [0] => 16.25 [1] => 57.33 )
Array ( [0] => 19.67 [1] => 33.5 [2] => 55.5 )
Array ( [0] => 7 [1] => 25.5 [2] => 75 [3] => 22 )
Demo
You could use array_chunk to split your array into pieces, the size being count($array) / $final_count, then use array_map to take the average value from each of those chunks (array_sum($chunk) / count($chunk)):
$array = [10,20,30,40,50,60];
$final_count = 3;
$new_array = array_map(function ($a) {
return array_sum($a) / count($a);
}, array_chunk($array, (int)(count($array) / $final_count)));
print_r($new_array);
Output
Array
(
[0] => 15
[1] => 35
[2] => 55
)
Demo on 3v4l.org
Note
This will give extra values on the end if the array length is not evenly divisible by $final_count (demo). You will need to pad the array out in that case to a multiple of that length using code such as this, which replicates the last value in the array:
while (count($array) % $final_count != 0) {
$array[] = end($array);
}
Demo on 3v4l.org

Getting separate different value in an array

I have this kind of problem that I can't get the same value in an array and separate the different value inside an array
I have done using for loop but it seems like my logic wasn't correct.
Value of $supplier_id is
Array (
[0] => 82
[1] => 82
[2] => 96
[3] => 96
[4] => 28
)
for($x = 0; $x < count($supplier_id); $x++){
for($i = 0; $i < count($supplier_id); $i++){
if($supplier_id[$x] == $supplier_id[$i]){
$same_supp[$x]['same_supp'] = $supplier_id[$x];
}else{
}
}
}
I want to store the values inside the array with the same value and separate the different value.
My expected output is
$same_supp[0] = array(0 => 82, 1 => 82);
$same_supp[1] = array(0 => 96, 1 => 96);
and separate the different value which is 28 and store it in different variable.
Group them, filter out the single occurrences, and remove the temporary keys.
Code: (Demo)
$array = [82, 82, 96, 96, 28];
foreach ($array as $v) {
$temp[$v][] = $v;
}
foreach ($temp as $a) {
if (count($a) != 1) {
$result[] = $a;
}
}
var_export($result);
Output:
array (
0 =>
array (
0 => 82,
1 => 82,
),
1 =>
array (
0 => 96,
1 => 96,
),
)
Since the inner loop ($i) also run on the same iteration as the outer loop ($x), it will not only find the duplicates, but also all of the elements.
You can fix it by skipping the check of the same item (when $i and $x are equal)
for($x = 0; $x < count($supplier_id); $x++){
for($i = 0; $i < count($supplier_id); $i++){
if ($x == $i) continue;
...
...

Make binary Pairing array from dynamic associative array on the basis of Keys, One Element from each Key

I'm Basically Creating Pair from a dynamic associative array in such a manner that I took 1 element from one key array and other element from other key array on which these two elements combine make pair 1. Problem is this a dynamic associative array it can have 4 Keys having arrays every key can have maximum two elements and minimum 1 elememt in its array and to make pair we should have two keys having 1 element on both side of these two keys array.
For Example
[parent_id] => Array
(
[9] => Array
(
[0] => 11
[1] => 12
)
[10] => Array
(
[0] => 13
[1] => 14
)
[20] => Array
(
[0] => 21
[1] => 22
)
[21] => Array
(
[0] => 23
)
)
This is an associative array which gives 3 pairs right now.
For Example
pair 1 contain: 11 , 13
pair 2 contain: 12 , 14
pair 3 contain: 21 , 23
Now the Issue is by using what methodology I can get my desire result.
Any Suggestions !!!!
Update 3
The last update didn't find all the possible pairs for one case. This version loops through differently, taking at most one element from each array before moving to the next one and pairing from there. It loops until there are insufficient values left to pair.
function find_pairs($array) {
// re-index to 0
$array = array_values($array['parent_id']);
// sort so the longest arrays are first
usort($array, function ($a, $b) { return count($b) - count($a); });
// output array
$pairs = array();
$c = count($array);
$i = 0;
// loop while there are enough values to pair (2 or more)
while (array_reduce($array, function ($c, $v) { return $c + count($v); }, 0) > 1) {
// make sure there are some elements in this array
while (!count($array[$i])) $i = ($i + 1) % $c;
// find the next array with a value
$j = ($i + 1) % $c;
while (!count($array[$j])) $j = ($j + 1) % $c;
// have we come full circle?
if ($j == $i) break;
// save the pair
$pairs[] = array(array_shift($array[$i]), array_shift($array[$j]));
// move on to the next array
$i = ($i + 1) % $c;
}
return $pairs;
}
Demo (includes all possible test cases) on 3v4l.org
Original answer
Here's one way to do this. Re-index the parent_id array to start at 0, and then loop through the array 2 elements at a time, combining all the values from each element. We use min to make sure we only pair as many values as there are in the smallest value array.
// re-index to 0
$array = array_values($array['parent_id']);
// output array
$pairs = array();
for ($i = 0; $i < count($array) - 1; $i += 2) {
for ($j = 0; $j < min(count($array[$i]), count($array[$i+1])); $j++) {
$pairs[] = array($array[$i][$j], $array[$i+1][$j]);
}
}
print_r($pairs);
Output:
Array (
[0] => Array ( [0] => 11 [1] => 13 )
[1] => Array ( [0] => 12 [1] => 14 )
[2] => Array ( [0] => 21 [1] => 23 )
)
Demo on 3v4l.org
Update
If you want to guarantee getting the maximum number of pairs from the array, sort to make the longest arrays come first:
$array = array_values($array['parent_id']);
// sort so the longest arrays are first
usort($array, function ($a, $b) { return count($b) - count($a); });
// output array
$pairs = array();
for ($i = 0; $i < count($array) - 1; $i += 2) {
for ($j = 0; $j < min(count($array[$i]), count($array[$i+1])); $j++) {
$pairs[] = array($array[$i][$j], $array[$i+1][$j]);
}
}
print_r($pairs);
Demo on 3v4l.org
Update 2
Based on further comments, it seems the only requirement for pairing is that the key of the array from which the elements from is not the same. This makes things a bit more complicated, but this function should do what you want:
function find_pairs($array) {
// re-index to 0
$array = array_values($array['parent_id']);
// sort so the longest arrays are first
usort($array, function ($a, $b) { return count($b) - count($a); });
// output array
$pairs = array();
for ($i = 0, $j = 1; $i < count($array) - 1; $i++) {
if (!count($array[$i])) continue;
while ($j <= $i || $j < count($array) && !count($array[$j])) $j++;
while (count($array[$i]) && isset($array[$j]) && count($array[$j])) {
$pairs[] = array(array_shift($array[$i]), array_shift($array[$j]));
// exhausted other arrays elements?
while ($j < count($array) && !count($array[$j])) $j++;
}
}
return $pairs;
}
Demo on 3v4l.org

After for-loop, returned array is wrong

I have something like that:
$n = 2;
$items = array();
$result = array(); // new array with random items
$random_items = array_rand( $items, $n );
for( $f=0; $f<=$n; $f++ ) {
$result[] = $items[$random_items[$f]];
}
$items is sth like
Array ( [0] => file1.jpg [1] => file2.png [2] => file3.jpg ... and so on )
This is working OK... but if I set $n to 1 then the script is not working or working incorrectly!
If $n == 2 (or more) the result array have last element's value empty
Array ( [0] => 20141125-17826a4b34.png [1] => 20141125-27fe57561d.jpg [2] => )
If $n == 1 (exactly) the result array is like
Array ( [0] => [1] => )
The result array should be the same format as items array but only with $n random items.
Thanks in advance!
Working
if( $n > 1 ) {
for( $f=0; $f<$n; $f++ ) {
$result[] = $items[$random_items[$f]];
}
}
elseif( $n == 1 ) {
$result[0] = $items[$random_items];
}
You should $f < $n instead of $f <= $n
for( $f=0; $f < $n; $f++ ) {
$result[] = $items[$random_items[$f]];
}
Because, when you're using $f <= $n its running up to 0,1 (when, $n = 1) OR 0,1,2 (when $n = 2) and you're missing the last indexed element.
When picking only one entry, array_rand() returns the key for a random
entry(not array).Otherwise, an array of keys for the random entries is returned.
So, This means, when you're using $n = 1, then $random_items is just a value(not array). eg.
for $n = 1, $random_items = 4;
but for $n >= 2, $random_items = [1, 6, 3, 6];

multiplication with *=

I have an array with these values:
array
0 =>
array
0 => int 1
1 => float 0.125
2 => float 0.5
3 => float 3
1 =>
array
1 => int 1
2 => float 5
3 => float 7
0 => float 8
2 =>
array
2 => int 1
3 => float 3
0 => float 2
1 => float 0.2
3 =>
array
3 => int 1
0 => float 0.33333333333333
1 => float 0.14285714285714
2 => float 0.33333333333333
And i want for each group the multiplication of each row like:
1*0.125*05*3
I am trying this code:
$final= array_fill(0, count($matrix), 0);
for ($i = 0; $i < count($matrix); $i++) {
$a = 1;
for ($j = 0; $j < count($matrix)-1; $j++) {
$final[$i] *= $matrix[$i][$j]*$matrix[$i][$a];
$a++;
}
}
but i got 0 for each multiplication row.
The code works well with +=, but:
1*0.125*05*3 = 0.1875 (this is the objective)
is different of
1*0.125+0.125*0.5+*0.5*3 = 16875
Any idea ?
Can you not just do
$final = array();
foreach( $matrix as $arr ) {
$final[] = array_product( $arr );
}
print_r( $final );
Which results in
Array ( [0] => 0.1875 [1] => 280 [2] => 1.2 [3] => 0.015873015873015 )
Alternatively, if you want to continue to do it your way:
$final= array_fill(0, count($matrix), 1);
for ($i = 0; $i < count($matrix); $i++) {
for ($j = 0; $j < count($matrix); $j++) {
$final[$i] *= $matrix[$i][$j];
}
}
I removed the -1 because that meant it missed the last element take 1*5*8*7 for example. Your way = 40 because the 7 was never multiplied. The above outputs the same result.
The neutral element for the multiplication is 1, not 0. You're filling your final array with zeros with this statement
$final= array_fill(0, count($matrix), 0);
and, obviously, when you do
$final[$i] *= $matrix[$i][$j];
everything will be zero as well. Thus, you have to replace the first line with this one:
$final= array_fill(0, count($matrix), 1);
0 * anything is 0. You initialized your array to all 0.

Categories