Group multidimensional array by key and sum values in PHP - php

There are similar questions on Stack Overflow but nothing quite like mine, and I also want to double check that I am doing this the most efficient way (resource wise).
I have surveys that are submitted and I want to tally the results. Each survey is saved in a multidimensional array like so:
Array ( [name] => Clark Kent [rating] => 5 )
These are coming from a loop as they are separate database entries.
So I am beginning by creating a new array with all these combined:
$mods = array();
$index = -1;
foreach($fields as $field) {
$index++;
$mods[$index]['name'] = $field['name'];
$mods[$index]['rating'] = $field['rating'];
}
Then I am grouping these so that all the ratings for the same name are together, so I can sum them later.
$groups = array();
foreach ($mods as $value) {
$groups[$value['name']][] = $value;
}
This produces the following:
Array (
[Clark Kent] => Array (
[0] => Array (
[name] => Clark Kent
[rating] => 5
)
[1] => Array (
[name] => Clark Kent
[rating] => 5
)
)
[Peter Parker] => Array (
[0] => Array (
[name] => Peter Parker
[rating] => 5
)
[1] => Array (
[name] => Peter Parker
[rating] => 5
)
)
[Bruce Wayne] => Array (
[0] => Array (
[name] => Bruce Wayne
[rating] => 5
)
[1] => Array (
[name] => Bruce Wayne
[rating] => 5
)
)
[Bruce Banner] => Array (
[0] => Array (
[name] => Bruce Banner
[rating] => 5
)
[1] => Array (
[name] => Bruce Banner
[rating] => 5
)
)
)
What I am trying to accomplish would be something like this:
<table>
<tr>
<td>Clark Kent</td>
<td>{average of all ratings}</td>
</tr>
</table>
I'm most of the way there, but I am stuck! I'm not sure how to get the grouped name that doesn't have any type of index or key so I can use that value for my table. Then I need to sum each grouped values.

I would do all the necessary math in the loop that reads the data from the database. Something like this:
$ratings = array();
while ($row = $result->fetch_assoc()) {
$name = $row['name'];
if (!isset($ratings[$name])) {
$ratings[$name] = array('count' => 1, 'sum' => $row['rating']);
}
else {
$ratings[$name]['count']++;
$ratings[$name]['sum'] += $row['rating'];
}
}
Then you can just output your table like so:
echo "<table>";
foreach ($ratings as $name => $r) {
echo "<tr><td>$name</td><td>" . round($r['sum'] / $r['count'], 1) . "</td></tr>";
}
echo "</table>";

To get average you can do something like:
foreach ($groups as $name => $group) {
$average = array_sum(array_column($group, 'rating')) / count($group);
echo $name;
}

You could simplify the problem in the first place in the structure you are using to handle those date
foreach($fields as $field) {
$mods[$field['name']][] = $field['rating'];
}
then just foreach with the key parameter
foreach($mods as $name => $mod) {
echo $name;
echo array_sum($mod) / count($mod);
}

Try to use the code below. Eliminating an extra loop to preparing group array.
$mods = array();
foreach($fields as $field) {
$mods[$field['name']][] = $field['rating'];
}
<table>
<tr>
<?php
if($mods) {
foreach($mods as $key=>$value) {
?>
<td><?php echo $key; ?></td>
<td><?php echo (array_sum($value)/count($value)); ?></td>
<?php
}
}
?>

Related

Multidimensional array in PHP using foreach loop [duplicate]

This question already has answers here:
Looping a multidimensional array in php
(3 answers)
Closed last year.
Here is an array from which I need to sort out the dept name, the full name and the salary , whose salary are above 10000rs.
The array is:
Array
(
[PHP] => Array
(
[0] => Array
(
[name] => Jay
[salary] => 8000
)
[1] => Array
(
[name] => Raj
[salary] => 15000
)
[2] => Array
(
[name] => Mihir
[salary] => 12000
)
)
[Flex] => Array
(
[0] => Array
(
[name] => Vijay
[salary] => 14000
)
)
[System] => Array
(
[0] => Array
(
[name] => Kishan
[salary] => 5000
)
)
)
I am totally confused inside the loops of foreach and don't know how to call each value from the array.
My code allows me to display only names.
Can i know what is the best way to print and work with multidimensional arrays in PHP.
My code:
foreach($newArray as $x=>$x_value){
foreach ($x_value as $y=> $y_value){
if($y_value['salary']>10000)
echo $y_value['name']." has ". $y_value['salary']. ", ";
}
}
Use the following, Tested and working
$filterArray = array();
$i = 0;
foreach($salary as $dept => $employee){
foreach($employee as $index => $data){
if($data['salary'] > 10000){
$filterArray[$i]['deprtment'] = $dept;
$filterArray[$i]['name'] = $data['name'];
$filterArray[$i]['salary'] = $data['salary'];
}
$i++;
}
}
Result :-
Array
(
[1] => Array
(
[deprtment] => PHP
[name] => Raj
[salary] => 15000
)
[2] => Array
(
[deprtment] => PHP
[name] => Mihir
[salary] => 12000
)
[3] => Array
(
[deprtment] => Flex
[name] => Vijay
[salary] => 14000
)
)
Your input is nested array. So you have to use foreach +for loop:
$final_array = array();
foreach($newArray as $x=>$x_value)
{
foreach ($i=0;$i<count($x_value);$i++)
{
if($x_value[$i]['salary']>10000)
{
if(isset($final_array[$x]))
{
array_push($final_array[$x],array("name"=>$x_value[$i]['name'],"salary"=>$x_value[$i]['salary']));
}
else
{
$final_array[$x] = array();
array_push($final_array[$x],array("name"=>$x_value[$i]['name'],"salary"=>$x_value[$i]['salary']));
}
}
}
}
$final_array print dep wise name & salary which is max than 10000
Output :
Array
(
[PHP] => Array
(
[0]=> Array
(
[name] => Raj
[salary] => 15000
)
[1]=> Array
(
[name] => Mihir
[salary] => 12000
)
)
[Flex] => Array
(
[0]=> Array
(
[name] => Vijay
[salary] => 14000)
)
)
)
Here is a simpler solution for looping over the arrays.
foreach ($bigArray as $department => $employees) {
foreach ($employees as $employee) {
if ($employee["salary"] > 10000) {
echo "Department: " . $department;
echo "Employee: " . $employee;
echo "Salary: " . $salary;
} else {
echo $person . " has no money.";
}
}
}
This will output what you were trying to print in your example.
Output for the first employee:
Department: <department name>
Employee: Raj
Salary: 15000
In the future, you should include the department names in your example array since your example doesn't have all of the information you are trying to print; we can't print something that doesn't exist.
I don't know, if i've got you correctly, but if you need to filter out all the people from the sub-arrays (PHP, Flex, System, ...) and then sort them either by their name or salary, you could do it in this or a similar way:
$array = [
'PHP' => [
[
'name' => 'Jay',
'salary' => 8000
],
[
'name' => 'Raj',
'salary' => 15000
],
[
'name' => 'Mihir',
'salary' => 12000
]
],
'Flex' => [
[
'name' => 'Vijay',
'salary' => 14000
]
],
'System' => [
[
'name' => 'Kishan',
'salary' => 5000
]
]
];
$array_people = [];
$array_sorted = [];
$sort_by = 'name'; // Array key name
$sort_desc = false;
$min_salary = 10000;
foreach ($array as $type => $people)
{
foreach ($people as $info)
{
if ($info['salary'] >= $min_salary) {
$array_sorted[] = $info[$sort_by];
$array_people[] = $info;
}
}
}
if ($sort_desc) {
// Sort descending
arsort($array_sorted);
} else {
// Sort ascending
asort($array_sorted);
}
$array_final = [];
foreach (array_keys($array_sorted) as $index)
{
$array_final[] = $array_people[$index];
}
print_r($array_final);
Output:
Array
(
[0] => Array
(
[name] => Mihir
[salary] => 12000
)
[1] => Array
(
[name] => Raj
[salary] => 15000
)
[2] => Array
(
[name] => Vijay
[salary] => 14000
)
)
The first thing you need to do, is to process the main array in a way, that allows you to keep just the items you want - this items need to be stored in a different (empty) array (in this case $array_people).
While detecting the items you need, you've to get out all the values you want to sort by - this can be done at the same time. It's just about creating a new array which will contain just the values you will sort by (in this case $array_sorted).
Then comes the easier part. The next thing to do is sorting the array. There exist a bunch of functions, that can help you with this.
The functions i've used (asort and arsort) are keeping the original key of the item, so you can sort the array containing all the people by the keys of the sorted array (see the code up above).
And that's all, now you have an array with filtered and sorted people :) ... hope, this helps you.
Okay after reading so many solutions I personally believe that some of them are totally confusing for a newbie so here is the solution I actually implemented which is totally simple and easy to understand the flow of multi-dimensional array.
foreach($newArray as $x=>$x_value){
foreach ($x_value as $y=> $y_value){
if($y_value['salary']>10000){
echo "<tr>";
echo "<td>"; echo $y_value['name']; echo "</td>";
echo "<td>"; echo $x; echo "</td>";
echo "<td>"; echo $y_value['salary']; echo "</td>";
echo "</tr>";
}
}
}
The output will be like, (if u use table )

Multiple array values to table php

Hello how to show values in table when i have a three arrays?
I have 3 three arrays: urls,name,rok
stdClass Object
(
[urls] => Array
(
[0] => Array
(
[key] => /film/Marsjanin-2015-715533
)
[1] => Array
(
[key] => /film/Pi%C4%99%C4%87dziesi%C4%85t+twarzy+Greya-2015-655761
)
)
[name] => Array
(
[0] => Array
(
[key] => Marsjanin
)
[1] => Array
(
[key] => Pięćdziesiąt twarzy Greya
)
)
[rok] => Array
(
[0] => Array
(
[key] => (2015)
)
[1] => Array
(
[key] => (2015)
)
)
)
I want show values in table like this but missing $valu3 to third row in table, how to do?
urls name rok
/film/Marsjanin-2015-715533 Marsjanin (2015)
/film/Pi%C4%99%C4%87dziesi%C4% Pięćdziesiąt twarzy Greya (2015)
This is my code:
foreach($results as $itemz => $valuez) {
foreach($valuez as $key1 => $value1) {
foreach($value1 as $key2 => $value2) {
if ($itemz=='urls'){
$valu1[] = str_replace("/film/", "film/", $value2);
}
if($itemz=='name'){
$valu2[] = $value2;
}
if($itemz=='rok'){
$valu3[] = $value2;
}
}
}
}
$Result = array_combine($valu1, $valu2);
//echo '<pre>'; print_r($Result); echo '</pre>';
foreach($Result as $key1 => $value1) {
echo '
<tr>
<th><input type="checkbox" value="'.$key1.'" name="list[]" /></th>
<th>'.$value1.' ()</th><th>'.$rating.'</th>
<th>'.$value1.'</th>
<th>'.$genres.'</th><th>Importuj</th>
</tr>';
}
You have an object that contains three arrays with identical index number, so you can perform only one foreach loop in this way:
foreach( $results->urls as $key => $array )
{
echo $results->urls[$key]['key'];
echo $results->name[$key]['key'];
echo $results->rok[$key]['key'];
}
All the first part of code can be deleted. In the example above I simply echo values, without reproducing your html structure, because I don't understand it (you have two $value1 and a lot of <th>... ), but you can easily change it in your preferred way, like this:
echo '<td>'.$results->urls[$key]['key'].'</td>';
( etc... )

Organize or group data from multidimensional array

I have a multidimensional array that I'm having difficulty trying to group and sort for a particular need. Here is the array:
Array (
[0] => Array (
[0] => Joe Smith
[1] => Array (
[0] => 3
[1] => 9
)
)
[1] => Array (
[0] => John Doe
[1] => Array (
[0] => 6
[1] => 12
)
)
[2] => Array (
[0] => Jack Frost
[1] => Array (
[0] => 2
[1] => 4
)
)
)
What I want to do is sort the numbers from smallest to shortest (i.e. 2,3,4,6,9,12), but also keep the names associated with those numbers. For example:
2 (Jack Frost),
3 (Joe Smith),
4 (Jack Frost),
6 (John Doe),
9 (Joe Smith),
12 (John Doe)
Any ideas how to sort by number and keep the names together? Thanks
UPDATE 1
Here is the PHP code I've used to list the numbers in order:
$users = get_users();
$names = array();
$days = array();
foreach( $users as $user ) {
$names[] = $user->display_name;
$days[] = $user->member_day;
}
$result = array_map( null, $names, $days );
$mdays = array();
foreach( $days as $d ) {
foreach( $d as $d2) {
$mdays[] = $d2;
}
}
for( $i; $i<=31; $i++ ) {
if( in_array($i, $mdays) ) {
echo $i . '<br>';
}
}
In the above code, $result prints out the above Array. Also, the for loop sorts the "days".
The end goal is to have 31 blocks and fill in the block by number with the name.
You can do something like as
$result = [];
foreach ($arr as $key => $value) {
foreach ($value[1] as $v) {
$result[$v] = $value[0];
}
}
ksort($result);
print_r($result);
Output:
Array
(
[2] => Jack Frost
[3] => Joe Smith
[4] => Jack Frost
[6] => John Doe
[9] => Joe Smith
[12] => John Doe
)
Note: This'll work fine till none of the array array contains the same key
something like this should work, and at the end you can soert you array
$final_array=array();
foreach (array as $arr){
foreach($arr as $aaa){
$final_array[]=array($aaa,$arr[0])
}
}

iterate through complex multidimensional array

Here is the output of some complex multidimensional array:
Array (
[0] => Array (
[#attributes] => Array ( [ID] => 114037469 [Name] => MJBDESIGN.ORG [Traffic] => 4 [BidCount] => 0 [Price] => $8 USD [ValuationPrice] => - [TimeLeft] => 3H 27M [RowID] => 1 )
)
[1] => Array (
[#attributes] => Array ( [ID] => 114136929 [Name] => TRAININGPROGRAMMEDESIGN.COM [Traffic] => 11 [BidCount] => 0 [Price] => $8 USD [ValuationPrice] => $3 USD [TimeLeft] => 3H 27M [RowID] => 2 )
)
)
How to iterate through each item and get the 'ID', 'Name' and etc of individual item? Thanks
This array is not so much complex.
$simpleArray = __YOUR_COMPLEX_ARRAY__;
foreach ($simpleArray as $array) {
$id = $array['#attributes']['ID'];
$name = $array['#attributes']['Name'];
}
foreach ($array as $r) {
$name = $r['#attributes']['Name'];
$id = $r['#attributes']['ID'];
# code ....
}
If you would like all attributes of each row:
foreach ($array as $n=>$r){
echo "Row {$n}\n";
foreach ($r as $k=>$v){
// Echo the data
echo "{$k}=>${v}\n";
}
}
Just easy way:
$array = // your long array;
foreach($array as $row)
{
$id = $row['#attributes']['Id'];
$name = $row['attributes']['Name'];
// do something with these variables
}
Try it like,
foreach ($yourarray as $val) {
echo $id = $val['#attributes']['ID'];
echo $name = $val['#attributes']['Name'];
}

Need help to understand result set from PDO

I have the following function executing PDO queries:
// removed error handling for presenting here
function getRows($sql) {
$stmt = $this->db->query($sql);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
}
The result is:
Array
(
[0] => Array
(
[id] => 1
[category] => Audi
)
[1] => Array
(
[id] => 2
[category] => BMW
)
[2] => Array
(
[id] => 3
[category] => Chrysler
)
)
The the following foreach code:
foreach($result as $key => $value ) {
echo $value.'<br/>';
}
outputs this:
Array
Array
Array
What can I do so it returns the following?
Audi
BMW
Chrysler
I understand that I could just do $value['category].
But that's not what I want to achieve / understand. I would like the resultset not to be an array of arrays.
try
foreach($result as $key => $value ) {
echo $value['category'].'<br/>';
}
Alternative
foreach($result as $k)
{
echo $k['category'];
}
The foreach loop splits up your array into key, value pairs. The key in your loop is the index of the array, the value is an array containing ID and Category.
To access the category simply do:
foreach($result as $key => $value ) {
echo $value['category'].'<br/>';
}

Categories