I am trying to find a way to allow me to count the number of times a value appears across multiple arrays as well as, for each unique value, the total count.
The data looks like the below:
Array ( [id] => 4383 [score] => 3 )
Array ( [id] => 4382 [score] => 4 )
Array ( [id] => 4381 [score] => 5 )
Array ( [id] => 4383 [score] => 7 )
Array ( [id] => 4383 [score] => 1 )
Array ( [id] => 4382 [score] => 2 )
Array ( [id] => 4381 [score] => 8 )
The above should return:
4383 - 3 - 11
4382 - 2 - 6
4381 - 2 - 13
I have used array_push and created one array called $output and looped using foreach to get a count of the id's using:
foreach($output as $row) {
$array[$row[0]]++;
}
This returns the correct count of id but I cannot get the total score for each id - I have tried:
foreach($output as $row) {
foreach($row as $r) {
$array[$row[0]]=$array[$row[1]]+$array[$r[1]];
}
}
but it returns zero for everything
Like below:
$result = array();
foreach ($data as $value) {
if (!isset($result[$value['id']])) {
$result[$value['id']] = array('count' => 0, 'sum' => 0);
}
$result[$value['id']]['count'] += 1;
$result[$value['id']]['sum'] += $value['score'];
}
$result = array();
foreach ($output as $row) {
if (!array_key_exists($row[0], $result)) {
$result[$row[0]] = array("Count" => 1, "Total" => $row[1]);
}
else {
$result[$row[0]]['Count'] += 1;
$result[$row[0]]['Total'] += $row[1];
}
}
print_r($result);
Related
This is a question for all the array specialists out there. I have an multi dimension array with a result as number (can be 0,1 or 2) and need the average for each grouped by parent.
In the example below the calculation would be:
subentry1_sub1 = 2 + 2 = 4 (4/2=2)
subentry1_sub2 = 1 + 1 = 2 (2/2=1)
So what I try to archive in PHP is the following result:
subentry1_sub1 average = 2
subentry1_sub2 average = 1
...
I already tried some solutions from similar questions. But with all the recursive functions I didn't managed to get it aggregated by the last child name (e.g. subentry1_sub1).
Any ideas?
EDIT:
subentry1_sub1 is 2 + 2 because its two times in the array
[entry1] => [subentry1] => [subentry1_sub1] => result
[entry2] => [subentry1] => [subentry1_sub1] => result
Array
(
[entry1] => Array
(
[subentry1] => Array
(
[subentry1_sub1] => Array
(
[value] => abc
[result] => 2
)
[subentry1_sub2] => Array
(
[value] => abc
[result] => 1
)
)
[subentry2] => Array
(
[subentry2_sub1] => Array
(
[value] => abc
[result] => 1
)
[subentry2_sub2] => Array
(
[value] => abc
[result] => 1
)
)
)
[entry2] => Array
(
[subentry1] => Array
(
[subentry1_sub1] => Array
(
[value] => abc
[result] => 2
)
[subentry1_sub2] => Array
(
[value] => abc
[result] => 1
)
)
[subentry2] => Array
(
[subentry2_sub1] => Array
(
[value] => abc
[result] => 1
)
[subentry2_sub2] => Array
(
[value] => abc
[result] => 1
)
)
)
)
Try this code. In this i have created a new array $sum which will add result value of same subentry childs with same key and another array $count which will count the number of times each key repeats
<?php
$data = array('entry1'=>array(
'subentry1'=>
array(
'subentry1_sub1'=>array('value'=>'abc','result'=>2),
'subentry1_sub2'=>array('value'=>'abc','result'=>1)
),
'subentry2'=>
array(
'subentry2_sub1'=>array('value'=>'abc','result'=>1),
'subentry2_sub2'=>array('value'=>'abc','result'=>1)
)
),
'entry2'=>array(
'subentry1'=>
array(
'subentry1_sub1'=>array('value'=>'abc','result'=>2),
'subentry1_sub2'=>array('value'=>'abc','result'=>1)
),
'subentry2'=>
array(
'subentry2_sub1'=>array('value'=>'abc','result'=>1),
'subentry2_sub2'=>array('value'=>'abc','result'=>1)
)
)
);
$sum = array();
$repeat = array();
foreach($data as $input){
foreach($input as $array){
foreach($array as $key=>$value){
if(array_key_exists($key,$sum)){
$repeat[$key] = $repeat[$key]+1;
$sum[$key] = $sum[$key] + $value['result'];
}else{
$repeat[$key] = 1;
$sum[$key] = $value['result'];
}}}}
echo "<pre>";
print_r($sum);
print_r($repeat);
foreach($sum as $key=>$value){
echo $key. ' Average = '. $value/$repeat[$key]."</br>";
}
Output
Array
(
[subentry1_sub1] => 4
[subentry1_sub2] => 2
[subentry2_sub1] => 2
[subentry2_sub2] => 2
)
Array
(
[subentry1_sub1] => 2
[subentry1_sub2] => 2
[subentry2_sub1] => 2
[subentry2_sub2] => 2
)
subentry1_sub1 Average = 2
subentry1_sub2 Average = 1
subentry2_sub1 Average = 1
subentry2_sub2 Average = 1
You can easily calculate avg now
Note : As you mentioned you are counting occurence of subentry1_sub1 etc so i did the same so it will also count whether key result exists or not
I know this is an old thread but im pretty sure there is a much easier way of doing this for anyone who is interested:
If you know the result will always be a number:
foreach($my_array as $entry_name => $entry_data)
{
foreach($entry_data as $sub_name => $sub_data)
{
$sub_results = array_column($sub_data, 'result');
$averages[$entry_name][$sub_name] = array_sum($sub_results)/count($sub_results);
}
}
If its possible the result could be NULL or empty, this will check it and return 'N/A' if there is no valid data to calculate an average from:
foreach($my_array as $entry_name => $entry_data)
{
foreach($entry_data as $sub_name => $sub_data)
{
$sub_results = array_filter(array_column($sub_data, 'result'));
$averages[$entry_name][$sub_name] = (count($sub_results) > 0 ? array_sum($sub_results)/count($sub_results) : 'N/A');
}
}
both of these solutions will give you an averages array that will output the average per subentry per entry.
Try this like,
<?php
$data=array('entry1'=>array(
'subentry1'=>
array(
'subentry1_sub1'=>array('value'=>'abc','result'=>3),
'subentry1_sub2'=>array('value'=>'abc','result'=>3)
),
'subentry2'=>
array(
'subentry2_sub1'=>array('value'=>'abc','result'=>2),
'subentry2_sub2'=>array('value'=>'abc','result'=>8)
)
),
'entry2'=>array(
'subentry1'=>
array(
'subentry1_sub1'=>array('value'=>'abc','result'=>6),
'subentry1_sub2'=>array('value'=>'abc','result'=>6)
),
'subentry2'=>
array(
'subentry2_sub1'=>array('value'=>'abc','result'=>10),
'subentry2_sub2'=>array('value'=>'abc','result'=>12)
)
)
);
foreach($data as $k=>$v){
echo "----------------$k---------------------\n";
if(is_array($v)){
foreach($v as $a=>$b){
if(is_array($b)){
echo $a.' average = ';
$c=array_keys($b);// now get *_sub*
$v1=isset($b[$c[0]]['result']) ? $b[$c[0]]['result'] : '';
$v2=isset($b[$c[1]]['result']) ? $b[$c[1]]['result'] : '';
echo ($v1+$v2)/2;
echo "\n";
}
}
}
}
Online Demo
In the meantime I found a simple working solution myself:
foreach ($data as $level2) {
foreach ($level2 as $level3) {
foreach ($level3 as $keyp => $level4) {
foreach ($level4 as $key => $value) {
if($key == 'result') $stats[$keyp] += $value;
}
}
}
}
With that you get the total for every key in an new array $stats.
But be sure to checkout the solution from user1234, too. It's working great and already includes the calculation of the average.
https://stackoverflow.com/a/39292593/2466703
This question already has answers here:
Group array data on one column and sum data from another column
(5 answers)
Closed 9 months ago.
I have the following array
Array (
[0] => Array
(
[0] => ALFA
[1] => 213
)
[1] => Array
(
[0] => ALFA
[1] => 151
)
[2] => Array
(
[0] => ALFA
[1] => 197
)
[3] => Array
(
[0] => BETA
[1] => 167
)
[4] => Array
(
[0] => ZETA
[1] => 254
)
[5] => Array
(
[0] => GAMA
[1] => 138
)
[6] => Array
(
[0] => GAMA
[1] => 213
)
)
And I would like to group the key[0] of the subarray so I can see how many equal keys it has.
Something like that:
ALFA => 3
BETA => 1
EPSI => 1
GAMA => 2
I tried with array_count_values, but without success.
foreach ($array as $value) {
echo '<pre>';
print_r(array_count_values($value));
echo '</pre>';
}
With that we have following result:
Array
(
[ALFA] => 1
[213] => 1
)
Array
(
[ALFA] => 1
[151] => 1
)
...
Array
(
[GAMA] => 1
[213] => 1
)
And after that I would like to sum the values of each group as well.
ALFA => 213 + 151 + 197
BETA => 167
ZETA => 254
GAMA => 138 + 213
I think that when we solve the first part of the problem, the second would follow easier with quite the same method.
The final purpose is to divide the sum of values by the number of occurrences of each key group, so we can have an average of the values just like that:
ALFA => (213+151+197) / 3 = 187
BETA => 167
ZETA => 254
GAMA => (138+213) / 2 = 175,5
This is not the main problem, but as I said, I'm stuck with the beginning of the solution and would appreciate any help.
I'm surprised at all the long and complicated answers. However, the initial foreach to model your data to something manageable is needed. After that you just need to do a really simple array_walk.
<?php
$result = array();
foreach ($array as $el) {
if (!array_key_exists($el[0], $result)) {
$result[$el[0]] = array();
}
$result[$el[0]][] = $el[1];
}
array_walk($result, create_function('&$v,$k', '$v = array_sum($v) / count($v);'));
?>
Result:
Array
(
[ALFA] => 187
[BETA] => 167
[ZETA] => 254
[GAMA] => 175.5
)
Solution for you is here:
Code:
$input = [
['alfa', 123],
['alfa', 223],
['alfa', 122],
['alfa', 554],
['alfa', 34],
['dalfa', 123],
['halfa', 223],
['dalfa', 122],
['halfa', 554],
['ralfa', 34]
];
$result = [];
foreach ($input as $node) {
if (isset($result[$node[0]])) {
$result[$node[0]] = ['sum' => $result[$node[0]]['sum'] + $node[1], 'count' => $result[$node[0]]['count'] + 1];
} else {
$result[$node[0]] = ['sum' => $node[1], 'count' => 1];
}
}
print_r($result);
foreach ($result as $key => &$data) {
$data = $data['sum'] / $data['count'];
}
print_r($result);
Output:
Array
(
[alfa] => Array
(
[sum] => 1056
[count] => 5
)
[dalfa] => Array
(
[sum] => 245
[count] => 2
)
[halfa] => Array
(
[sum] => 777
[count] => 2
)
[ralfa] => Array
(
[sum] => 34
[count] => 1
)
)
Array
(
[alfa] => 211.2
[dalfa] => 122.5
[halfa] => 388.5
[ralfa] => 34
)
$sort = array();
foreach ($array as $value) {
$sort[$value[0]][] = $value[1];
}
then you count how many keys each has
$keys = array();
foreach($sort as $k => $v) {
$keys[$k] = count($v);
}
then for calculating the amount
$sum = array();
$average = array();
foreach($sort as $k => $v) {
$amount = 0;
foreach($v as $val) {
$amount += $val;
}
$sum[$k] = $amount;
$average[$k] = $amount / $keys[$k];
}
HOWEVER, If you want all the details in one array:
$final = array();
foreach ($array as $value) {
$final[$value[0]]["values"][] = $value[1];
}
foreach($final as $k => $v) {
$final[$k]["amount"] = count($v['values']);
$amount = 0;
foreach($v['values'] as $val) {
$amount += $val;
}
$final[$k]["sum"] = $amount;
$final[$k]["average"] = $amount / $final[$k]["amount"];
}
example: http://jdl-enterprises.co.uk/sof/25789697.php
Includes Output
Just copy the codes to your favorite text editor, sure it works perfectly.
$items = [
['ALFA',213],
['ALFA',151],
['ALFA',197],
['BETA',167],
['ZETA',254],
['GAMA',138],
['GAMA',213]
];
echo '<pre>' . print_r($items,true) . '</pre>';
$result;
foreach ($items as $value) {
# code...
if (isset($result[$value[0]])) {
$sum = $result[$value[0]]['sum'] + $value[1];
$count = $result[$value[0]]['count'] + 1;
$result[$value[0]] = ['sum' => $sum , 'count' => $count, 'divided' => ($sum / $count)];
} else {
$result[$value[0]] = ['sum' => $value[1] , 'count' => 1 , 'divided' => ($value[1] / 1) ];
}
}
echo '<pre>' . print_r($result,true) . '</pre>';
$myArray = [
["ALFA",213],
["ALFA",151],
["ALFA",197],
["BETA",167],
["ZETA",254],
["GAMA",138],
["GAMA",213]
];
$a1 = array(); //TEMPORARY ARRAY FOR KEEPING COUNT & TOTAL VALUES
$res = array(); //ARRAY USED TO KEEP RESULT
foreach($myArray as $val)
{
//AVOID PESKY NOTICES FOR UNDEFINED INDEXES
if ( !array_key_exists($val[0],$a1) ) {
$a1[$val[0]] = array("count" => 0,"total" => 0);
$res[$val[0]] = 0;
}
//INCREMENT THE COUNT OF INSTANCES OF THIS KEY
$a1[$val[0]]["count"]++;
//INCREMENT THE TOTAL VALUE OF INSTANCES OF THIS KEY
$a1[$val[0]]["total"]+=$val[1];
// UPDATE RESULT ARRAY
$res[$val[0]] = $a1[$val[0]]["total"] / $a1[$val[0]]["count"];
}
print_r($res);
Should result in:
Array
(
[ALFA] => 187
[BETA] => 167
[ZETA] => 254
[GAMA] => 175.5
)
Sample: http://phpfiddle.org/lite/code/a7nt-5svf
I have this array which has more then 100 results but some of these has same sub array key. I would like to sum array element which has same key which is [/xyx/888350] in this example. However, I want to keep the format as it is which is two dimensional.
Array
(
[0] => Array
(
[/xyx/888350] => /xyx/888350
[visitors] => 1
[pageviews] => 2
[uniquepageviews] => 1
)
[1] => Array
(
[/xyx/888350] => /xyx/888350
[visitors] => 1
[pageviews] => 3
[uniquepageviews] => 1
)
[2] => Array
(
[/xyx/888350] => /xyx/888350
[visitors] => 1
[pageviews] => 2
[uniquepageviews] => 1
)
[3] => Array
(
[/xyx/102254] => /xyx/102254
[visitors] => 1
[pageviews] => 2
[uniquepageviews] => 1
)
)
I am expecting out put something like below:
Array
(
[0] => Array
(
[/xyx/888350] => /xyx/888350
[visitors] => 2
[pageviews] => 7
[uniquepageviews] => 2
)
[1] => Array
(
[/xyx/102254] => /xyx/102254
[visitors] => 1
[pageviews] => 3
[uniquepageviews] => 1
)
)
Thanks in advance.
Loop the array, and store the results in a temporary array, by using the first value as a key:
$input = /*your example data here*/;
$result = array();
foreach($input as $data){
$keys = array_keys($data);
$key = $keys[0]; //get the first key of the array a.k.a '/xyx/888350'
if(isset($result[$key])){
//sum the values if we have this key
$result[$key]['visitors'] += $data['visitors'];
$result[$key]['pageviews'] += $data['pageviews'];
$result[$key]['uniquepageviews'] += $data['uniquepageviews'];
}else{
$result[$key] = $data;
}
}
//drop the extra keys and return a indexed array with the summed values
return array_values($result);
$results=$service->data_ga->get("");
$stats = array();
for ($i=0; $i < count($stats_results=$results->getRows()) ; $i++)
{
$stats[]=array(
'path'=>$stats_results[$i][1],
'visitors'=>$stats[$i]['visitors'] + $stats_results[$i][2],
'pageviews'=>$stats[$i]['visitors'] + $stats_results[$i][3],
'uniquepageviews'=>$stats[$i]['visitors'] + $stats_results[$i][4]
);
}
$result = array();
foreach($stats as $data){
$keys = array_keys($data);
$key = $keys[0]; //get the first key of the array a.k.a '/xyx/888350'
if(isset($result[$key]))
{
//sum the values if we have this key
$result[$key]['visitors'] += $data['visitors'];
$result[$key]['pageviews'] += $data['pageviews'];
$result[$key]['uniquepageviews'] += $data['uniquepageviews'];
}else{
$result[$key] = $data;
}
}
echo "<pre>";
print_r($result);
Output:
Array
(
[path] => Array
(
[path] => /path/888350
[visitors] => 3
[pageviews] => 7
[uniquepageviews] => 3
)
)
Thanks both of you. As time goes on I will also answer questions other people have. I have just started my career. Thank you guys :)
Array
(
[updateCategories] => Array
(
[products] => Array
(
[0] => Array
(
[cat_id] => 3
[position] => 2
[product_id] => 8
)
[1] => Array
(
[cat_id] => 4
[position] => 11
[product_id] => 8
)
[2] => Array
(
[cat_id] => 3
[position] => 4
[product_id] => 39
)
[3] => Array
(
[cat_id] => 4
[position] => 9
[product_id] => 8
)
[4] => Array
(
[cat_id] => 3
[position] => 6
[product_id] => 41
)
[5] => Array
(
[cat_id] => 11
[position] => 7
[product_id] => 8
)
The above array is my output array but I need to get all cat_id of product_id=8. How can I do this?
$newarr = array();
foreach( $arr['updateCategories']['products'] as $myarr)
{
if($myarr['product_id'] == 8)
$newarr[] = $myarr['cat_id'];
}
The simpliest solution is
$result = array();
foreach($yourArray['updateCategories']['products'] as $product)
if($product['product_id] == 8)
$product[] = $product['cat_id'];
where $yourArray is the array which dump you have published.
Try something like this:
$arr = array();
foreach ($products as $key => $value)
{
if($value['product_id'] == 8)
{
$arr[] = $key;
}
}
print_r($arr); // <-- this should output the array of products with key as 8
Use this
foreach($array['updateCategories']['products'] as $product) {
if(isset($product['product_id']) && $product['product_id']==8) {
//do anything you want i am echoing
echo $product['cat_id'];
}
}
You can use array_filter.
function filterProducts($product) {
return ($product['product_id'] == 8);
}
$myProducts = array_filter(
$myArray['updateCategories']['products'],
'filterProducts'
);
Where $myArray is the array displayed in your post.
Can handle this by doing something like this
$matching_products = array();
foreach ($products as $key => $value) {
if($value['product_id'] == 8) {
$matching_products[] = $value['cat_id'];
}
}
which'll leave you with an array of cat ids that have a product id of 8
This should be able to retrieve all of the cat_id's from a given product_id. This function yields an object that can be iterated over to retrieve all the values it contains.
<?PHP
public function GetCatIdsByProductId($productId)
{
foreach($updateCategories=>products as $key=>$product)
{
if (isset($product=>product_id) && $product=>product_id == 8)
{
yield $product=>cat_id;
}
}
}
//Usage
$catIds = GetCatIdsByProductId(8);
var_dump($catIds);
A more generic version of this function can be constructed to retrieve a given key from a comparison on a given property value.
public function GetPropertyByPropertyComparison(array $list, $propRet, $propCompare, $compValue)
{
foreach($list as $key=>$product)
{
if (isset($product=>{$propCompare}) && $product=>{$propCompare} == $compValue)
{
yield $product=>{$propRet};
}
}
}
//usage
$cats = GetPropertyByPropertyComparison($updateCategories=>products, "cat_id", "product_id", 8);
var_dump($cats);
?>
I have these two arrays result in print_r:
Array ( [0] => multidesign1 [1] => multidesign1 [2] => multidesign2 [3] => multidesign2 )
Array ( [0] => 30 [1] => 7 [2] => 40 [3] => 1 )
The actual contents should be:
multidesign1 has 30 and 7 so its 37 while multidesign2 has 40 and 1 so its 41.
Can I combine these two arrays so I could come up with multidesign1=>37 and multidesign2=>41 ?
Thanks.
$newArray = array();
foreach(range(0, count($firstArray) - 1) as $index) {
if(isset($newArray[$index])) {
$newArray[$index] += $secondArray[$index];
} else {
$newArray[$index] = $secondArray[$index];
}
}
Is that something like what you're looking for?
$result = array();
foreach ($array1 as $i => $key) {
$result[$key] += $array2[$i];
}