I have an array which has multiple sets of data.
Is it possible to sum elements (not all) of the array. For example, is it possible to sum the first 5 sets of data in an array, then then next 7, then the next three etc.
EDIT:
I've tried the following but with not joy:
for ($p=0; $p<=8; $p++){
$tot = 0;
$resp = 0;
$tot = $tot + $row4['Total_Staff'];
$resp = $resp + $row4['Total_Resp'];
}
Clearly I am not using this correctly!
Array Output (print_r output):
Array ( [department] => Central>ACME>BusDev [Total_Staff] => 4 [Total_Resp] => 0 )
Array ( [department] => Central>ACME>ChemDev [Total_Staff] => 7 [Total_Resp] => 0 )
Array ( [department] => Central>ACME>Admin [Total_Staff] => 1 [Total_Resp] => 0 )
Array ( [department] => Central>ACME>Chemistry [Total_Staff] => 4 [Total_Resp] => 0 )
Use array_splice() to remove $numOfElems elements from the array and the return them. Use array_sum() to calculate the sum. Repeat the process until the array is empty.
$array = array(/* your array */)
$sets = array(5,7,3);
$sum_arr = array();
foreach ($sets as $numOfElems) {
while (!empty($array)) {
$elem_arr = array_splice($array, 0, $numOfElems);
$sum[] = array_sum($elem_arr);
}
}
print_r($sum_arr);
This will repeat the process with the same sets until it reaches the end of array. If you only want count($sets) number of iterations, then perhaps, you could change while to if.
Demo
Related
Question:
How can I iterate below so it checks existence of key "round_1", next script run it should check existense of key "round_2", etc. Everytime it would encounter that the key is missing it should create the key.
It is working with "round_1" as expected.
<?php
// Create array skeleton.
$array_skeleton = array_fill(1, 3, "");
print_r($array_skeleton);
// Populate the skeleton with random numbers, values [1 to 6].
foreach($array_skeleton as $key => $value) {
$populated_array[$key] = random_int(1, 6);
};
print_r($populated_array);
// Create empty array for purpose to become multidimensional array.
$scorecard = [];
// Check if [round_1] is missing, if so create [round_1] and populate it.
if(!array_key_exists("round_1", $scorecard)) {
echo "round_1 is missing, creating it";
$scorecard["round_1"] = $populated_array;
}
print_r($scorecard);
Outcome works fine as expected, after first script run:
(
[round_1] => Array
(
[1] => 3
[2] => 4
[3] => 1
)
)
Expected outcome, after second script run:
Note! It is correct that the values would be different per each round since they are randomly created.
(
[round_1] => Array
(
[1] => 3
[2] => 4
[3] => 1
)
[round_2] => Array
(
[1] => 1
[2] => 4
[3] => 2
)
)
I think your entire code can be simplify:
first define function for create array with random number:
function createRandomNumberArray($numOfElem, $maxRange) {
for ($i = 0; $i < $numOfElem; $i++)
$res[] = random_int(1, $maxRange);
return $res;
}
Second, assuming your keys are made of "round_#INT#" pattern you can do
$biggest = max(array_map(function ($e) {$p = explode("_", $e); return $p[1];}, array_keys($arr)));
And now do:
$newKey = "round_" . ($biggest + 1);
$scorecard[$newKey] = createRandomNumberArray(3,6);
Reference: array-map, explode, max, random-int
I have an array of elements which I queried from the mongoDB.
This array has the id of a device and value of this device's consumptions.
For example there are 3 different ids -> 18,5,3 and multiple mixed values.
// first record of 18 so get value.
$row[0]["id"] = 18;
$row[0]["value"] = 100;
// not first record of 18 so ignore and move to the next record
$row[1]["id"] = 18;
$row[1]["value"] = 40;
// first record of 5 so get value.
$row[2]["id"] = 5;
$row[2]["value"] = 20;
// not first record of 18 so ignore and move to the next record
$row[3]["id"] = 18;
$row[3]["value"] = 30;
// first record of 3 so get value.
$row[4]["id"] = 3;
$row[4]["value"] = 20;
//not first record of 5 so ignore and move to the next record**
$row[5]["id"] = 5;
$row[5]["value"] = 30;
// not first record of 18 so ignore and move to the next record
$row[6]["id"] = 18;
$row[6]["value"] = 10;
...
....
What I am trying to do is loop through this $row array and get the most recent value of the id.
For example in above example what I want to return is:
id value
18 100
5 20
3 20
How can I do that kind of logic?
It can be done in several ways. The easiest one is to use a foreach:
$result = array();
foreach ($row as $i) {
if (! array_key_exists($i['id'], $result)) {
$result[$i['id']] = $i['value'];
}
}
# Verify the result
print_r($result);
The output is:
Array
(
[18] => 100
[5] => 20
[3] => 20
)
The same processing, but using array_reduce():
$result = array_reduce(
$row,
function(array $c, array $i) {
if (! array_key_exists($i['id'], $c)) {
$c[$i['id']] = $i['value'];
}
return $c;
},
array()
);
If you want to keep only the first occurrence of each 'id' then just add the values to an aggregate array - but only if they haven't been added already. Then grab the values of the aggregate array.
https://tehplayground.com/NRvw9uJF615oeh6C - press Ctrl+Enter to run
$results = array();
foreach ($row as $r) {
$id = $r['id'];
if (! array_key_exists($id, $results)) {
$results[$id] = $r;
}
}
$results = array_values($results);
print_r($results);
Array
(
[0] => Array
(
[id] => 18
[value] => 100
)
[1] => Array
(
[id] => 5
[value] => 20
)
[2] => Array
(
[id] => 3
[value] => 20
)
)
Try this
$alreadyfound = []; // empty array
$result = [];
foreach ($row as $item)
{
if (in_array($item["id"], $alreadyfound))
continue;
$alreadyfound[] = $item["id"]; // add to array
$result[] = $item;
}
The result
Array
(
[0] => Array
(
[id] => 18
[value] => 100
)
[1] => Array
(
[id] => 5
[value] => 20
)
[2] => Array
(
[id] => 3
[value] => 20
)
)
The array_unique() function is exactly what you are looking at.
See the documentation here : array_unique() documentation
Using array_column with an index key will almost do it, but it will be in the reverse order, so you can reverse the input so that it works.
$result = array_column(array_reverse($row), 'value', 'id');
This question already has answers here:
How to merge two arrays by summing the merged values [duplicate]
(3 answers)
Closed 5 months ago.
I would like to merge array by conditions. If array keys match then add the values, if not then retain the value.
Here are my arrays:
Array1
(
[1] => 199
[3] => 1306
[5] => 199
)
Array2
(
[3] => 199
[4] => 199
)
My desired result is:
Result
(
[1] => 199
[3] => 1505
[4] => 199
[5] => 199
)
I used if-else conditions, but it's repeating the value which is already matched.
Here is my coding attempt:
$all=array();
foreach($sall as $sskey => $ssvalue){
foreach($upgradesall as $uukey => $uuvalue){
//$sskey==$uukey?$all[] = array("id"=>$sskey, "amount"=>$ssvalue+$uuvalue):($sskey!=$uukey? $all[] = array("id"=>$sskey, "amount"=>$ssvalue):($uukey!=$sskey?$all[] = array("id"=>$uukey, "amount"=>$uuvalue):''));
if($sskey===$uukey){
$all[] = array("id"=>$sskey, "amount"=>$ssvalue+$uuvalue);
}elseif($sskey!=$uukey){
$all[] = array("id"=>$sskey, "amount"=>$ssvalue);
}elseif($uukey!=$sskey){
$all[] = array("id"=>$uukey, "amount"=>$uuvalue);
}
}
}
I think the problem is simpler than it looks. You really only need a conditional to preclude undefined offset notices. Just iterate all keys and values in both arrays and add the values to the corresponding key in the merged array.
foreach ([$a1, $a2] as $a) { // iterate both arrays
foreach ($a as $key => $value) { // iterate all keys+values
$merged[$key] = $value + ($merged[$key] ?? 0); // merge and add
}
}
Really, the line that actually does the addition ($merged[$key] = $value + ($merged[$key] ?? 0);) could be reduced to $merged[$key] += $value;. That would still work, but it would produce a bunch of undefined offset notices. So instead we can set the key equal to the value plus either the previous value (if it exists) or zero.
If you're still using PHP 5, you can use a ternary instead of the null coalescing operator (??), like this:
$merged[$key] = $value + (isset($merged[$key]) ? $merged[$key] : 0);
The output won't be in the same order shown in your desired result, but you can use ksort($merged); to accomplish that
First you can merge the arrays by merging all values in the same key:
$allKeys = array_unique(array_merge(array_keys($arr1),array_keys($arr2)));
$result = [];
foreach ($allKeys as $key) {
$result[$key] = [];
if (array_key_exists($key,$arr1)) {
$result[$key][] = $arr1[$key];
}
if (array_key_exists($key,$arr2)) {
$result[$key][] = $arr2[$key];
}
}
This will result in:
Array
(
[1] => Array
(
[0] => 199
)
[3] => Array
(
[0] => 1306
[1] => 199
)
[5] => Array
(
[0] => 199
)
[4] => Array
(
[0] => 199
)
)
Then you can map them according to your conditions:
$endResult = array_map('array_sum',$result);
Result:
Array
(
[1] => 199
[3] => 1505
[5] => 199
[4] => 199
)
If you want the keys to be sorted you can run them through a ksort as well
Check the code:
http://sandbox.onlinephpfunctions.com/code/3eb23310f0fd8de8174a5caf8b2b91d4b7562b6b
You could achieve that by
$all = array_merge($arr1,$arr2); // existing elements in arr1 are replaced by arr2 else merge into new array_merge
//then add replaced elememnts value
foreach($arr1 as $k=>$v)
{
if(array_key_exists($k,$all))
{
$all[$k] = $all[$k] + $v;
}
}
Let's say we have arrays like below.
$arr00 = [0,1,2,...,9]; // It includes 9 arrays. So the score should be 9.
$arr01 = [0,1,...,8]; // score = 8
...
$arr09 = [0]; // score = 0
ArrScore (definition): If an array include an array with all elements it
gets one point. So in this case $arr00's total score is 9. Because it
includes all other 9 arrays. And $arr09's score will be 0.
Actual Conditions
Our array elements could be random numbers. (not sequent orders ascending +1)
There could be thousands of arrays.
Our arrays are always flat. (no duplicated element in an array)
We are using php (any theoretical approach is also ok)
Think that you have a standard PC and you will order these arrays everyday once. (No need for the result of "which arr eats which ones". Just ArrScores.)
Goal is to order arrays by ArrScore. And we need ArrScores. What should be the approach? (Theoretical or practical)
If I understood right, this might help:
function compare($a,$b) {
if(count(array_intersect($a, $b)) == count($a)) return -1;
else return 1;
}
$arr0 = [0,2,4,7];
$arr1 = [7,0,2,9,4];
$arr2 = [4,2];
$arr = [$arr0,$arr1,$arr2];
usort($arr,"compare");
foreach($arr as $a) {
print_r($a);
}
prints:
Array ( [0] => 4 [1] => 2 ) Array ( [0] => 0 [1] => 2 [2] => 4 [3] => 7 ) Array ( [0] => 7 [1] => 0 [2] => 2 [3] => 9 [4] => 4 )
EDIT:
Compute the ArrayScore for each array:
$arr0 = [0,2,4,7];
$arr1 = [7,0,2,9,4];
$arr2 = [4,2];
$arr = [$arr0,$arr1,$arr2];
$arrayScores = [];
//initialize the Scores with 0
foreach($arr as $a){
$arrayScores[] = 0;
}
//run through all arrays
for($i=0;$i<count($arr);$i++){
//with $j=$i+1, every combination is only checked once
for($j=$i+1; $j<count($arr);$j++){
if(count(array_intersect($arr[$j], $arr[$i])) == count($arr[$j])) {
$arrayScores[$i]++;
}
if(count(array_intersect($arr[$i], $arr[$j])) == count($arr[$i])){
$arrayScores[$j]++;
}
}
}
I have the array:
$total =array();
Array (
[0] => Array
(
[0] => 1
[1] => 3
)
[1] => Array
(
[0] => 6
[1] => 7
[2] => 8
)
[2] => Array
(
[0] => 9
[1] => 10
)
)
I need to dynamically change each array into an indexed array for a Cartesian function.
Here is how I need the code to look for the function to work correctly:
$count = cartesian(
Array(1,3),
Array(6,7,8),
Array(9,10)
);
Any help would be greatly appreciated! I have tried flattening, looping, using array_values, using just the array itself and I keep falling short.
Thanks
Nick
function cartesian() {
$_ = func_get_args();
if(count($_) == 0)
return array(array());
$a = array_shift($_);
$c = call_user_func_array(__FUNCTION__, $_);
$r = array();
foreach($a as $v)
foreach($c as $p)
$r[] = array_merge(array($v), $p);
return $r;
}
$count = call_user_func('cartesian', array($total));
print_r($count);
Your arrays already look exactly the way you want them to. array(1,3) is the same as array(0 => 1, 1 => 3) and both are an array with the value 1 at key 0 and 3 at key 1. Exactly what the debug output shows you.
It seems you just need to pass them as separate arguments to the function. E.g.:
cartesian($total[0], $total[1], $total[2])
For dynamic lengths of arrays, do:
call_user_func_array('cartesian', $total)
I believe that your $total array is multi-dimensional array with numeric indexed. So yo can try like this
$count = cartesian($total[0], $total[1], $total[2]);