This question already has answers here:
multidimensional array array_sum
(10 answers)
Closed 5 years ago.
I need help regarding foreach and arrays in PHP
Say I have the following array:
$orders = array (
0 =>
array (
'company' => 'Company 1',
'total' => '5',
),
1 =>
array (
'company' => 'Company 2',
'total' => '10',
),
2 =>
array (
'company' => 'Company 1',
'total' => '15',
),
3 =>
array (
'company' => 'Company 1',
'total' => '5',
),
4 =>
array (
'company' => 'Company 3',
'total' => '12',
)
);
Order 1 is 5 for Company 1
Order 2 is 10 for Company 2
Order 3 is 15 for Company 1
Order 4 is 5 for Company 2
Order 5 is 12 for Company 3
I want the output to show the company name and the accumulative total of each company's orders
For example:
Company 1 20
Company 2 15
Company 3 12
Just create another array that will track the orders.
$companies = array();
foreach ($orders as $order) {
if (array_key_exists($order["company"], $companies)) {
$companies[$order["company"]] += $order["total"];
} else {
$companies[$order["company"]] = $order["total"];
}
}
First, we check if the company is already in the companies array, if it is then we add the total to that company's current total.
Otherwise, we just create a new key and store the total.
Additionally, you can write (int)$order["total"] to typecast into integer.
This might be useful to ensure that you have the correct data.
array_reduce() solution:
$groups = array_reduce($orders, function($r, $a) {
$k = $a['company'];
(isset($r[$k]))? $r[$k] += $a['total'] : $r[$k] = $a['total'];
return $r;
}, []);
foreach ($groups as $k => $v) {
printf("%-20s%d\n", $k, $v);
}
The output:
Company 1 25
Company 2 10
Company 3 12
One way to do this with a foreach loop where you increment some variable :
// Your array
$array = array(...);
// Init of the sum of each total for each company
$c1 = 0;
$c2 = 0;
$c3 = 0;
// You loop through your array and test the output
foreach ($array as $order => $value_array) {
switch($value_array['company']) {
case 'Company 1' : $c1 += intval($value_array['total']); break;
case 'Company 2' : $c2 += intval($value_array['total']); break;
case 'Company 3' : $c3 += intval($value_array['total']); break;
}
}
//$c1 will be the sum for company 1;
//$c2 for the company 2;
//$c3 for the company 3.
Is it what you are looking for?
Just another way: array_walk
$result = array();
array_walk($orders, function ($element) use (&$result) {
$company = $element['company'];
if (!isset($result[$company]))
$result[$company] = 0;
$result[$company] += $element['total'];
});
For this input:
$orders = array(
0 =>
array(
'company' => 'Company 1',
'total' => '5',
),
1 =>
array(
'company' => 'Company 2',
'total' => '10',
),
2 =>
array(
'company' => 'Company 1',
'total' => '15',
),
3 =>
array(
'company' => 'Company 1',
'total' => '5',
),
4 =>
array(
'company' => 'Company 3',
'total' => '12',
)
);
The output will be:
array(3) {
["Company 1"]=>
int(25)
["Company 2"]=>
int(10)
["Company 3"]=>
int(12)
}
Related
I have this array :
(
[id] => block_5df755210d30a
[name] => acf/floorplans
[data] => Array
(
[floorplans_0_valid_for_export] => 0
[floorplans_0_title] => title 1
[floorplans_0_house_area] => 40m²
[floorplans_0_bedrooms] => 1
[floorplans_1_valid_for_export] => 1
[floorplans_1_title] => title xx
[floorplans_1_house_area] => 90m²
[floorplans_1_bedrooms] => 2
[floorplans_2_valid_for_export] => 1
[floorplans_2_title] => title 2
[floorplans_2_house_area] => 50m²
[floorplans_2_bedrooms] => 1
[floorplans] => 3
)
)
As we can see in the data, we have fields (floorplans_X_valid_for_export).
What I want to do is to get the data only when this field equal to 1.
So from the given example, I want to keep only these fields:
[floorplans_1_valid_for_export] => 1
[floorplans_1_title] => title xx
[floorplans_1_house_area] => 90m²
[floorplans_1_bedrooms] => 2
[floorplans_2_valid_for_export] => 1
[floorplans_2_title] => title 2
[floorplans_2_house_area] => 50m²
[floorplans_2_bedrooms] => 1
This is an odd schema, but it can be done by iterating through the array and searching for keys where "valid_for_export" equals 1, and then using another array of field "stubs" to get the associated items by a unique identifier of X in floorplans_X_valid_for_export
$array = [
'floorplans_0_valid_for_export' => 0,
'floorplans_0_title' => 'title 1',
'floorplans_0_house_area' => '40m²',
'floorplans_0_bedrooms' => 1,
'floorplans_1_valid_for_export' => 1,
'floorplans_1_title' => 'title xx',
'floorplans_1_house_area' => '90m²',
'floorplans_1_bedrooms' => '2',
'floorplans_2_valid_for_export' => 1,
'floorplans_2_title' => 'title 2',
'floorplans_2_house_area' => '50m²',
'floorplans_2_bedrooms' => 1,
'floorplans' => 3
];
$stubs = [
'floorplans_%s_valid_for_export',
'floorplans_%s_title',
'floorplans_%s_house_area',
'floorplans_%s_bedrooms'
];
$newArr = [];
foreach ($array as $key => $value) {
if (strpos($key, 'valid_for_export') && $array[$key] == 1) {
$intVal = filter_var($key, FILTER_SANITIZE_NUMBER_INT);
foreach ($stubs as $stub) {
$search = sprintf($stub, $intVal);
if (isset($array[$search])) {
$newArr[$search] = $array[$search];
} else {
// key can't be found, generate one with null
$newArr[$search] = null;
}
}
}
}
echo '<pre>';
print_r($newArr);
Working: http://sandbox.onlinephpfunctions.com/code/23a225e3cefa2dc9cc97f53f1cbae0ea291672c0
Use a parent loop to check that the number-specific valid_for_export value is non-empty -- since it is either 0 or non-zero.
If so, then just push all of the associated elements into the result array.
Some reasons that this answer is superior to the #Alex's answer are:
Alex's parent loop makes 13 iterations (and the same number of strpos() calls); mine makes just 3 (and only 3 calls of empty()).
$array[$key] is more simply written as $value.
Sanitizing the $key to extract the index/counter is more overhead than necessary as demonstrated in my answer.
Code (Demo)
$array = [
'floorplans_0_valid_for_export' => 0,
'floorplans_0_title' => 'title 1',
'floorplans_0_house_area' => '40m²',
'floorplans_0_bedrooms' => 1,
'floorplans_1_valid_for_export' => 1,
'floorplans_1_title' => 'title xx',
'floorplans_1_house_area' => '90m²',
'floorplans_1_bedrooms' => '2',
'floorplans_2_valid_for_export' => 1,
'floorplans_2_title' => 'title 2',
'floorplans_2_house_area' => '50m²',
'floorplans_2_bedrooms' => 1,
'floorplans' => 3
];
$labels = ['valid_for_export', 'title', 'house_area', 'bedrooms'];
$result = [];
for ($i = 0; $i < $array['floorplans']; ++$i) {
if (!empty($array['floorplans_' . $i . '_valid_for_export'])) {
foreach ($labels as $label) {
$key = sprintf('floorplans_%s_%s', $i, $label);
$result[$key] = $array[$key];
}
}
}
var_export($result);
Output:
array (
'floorplans_1_valid_for_export' => 1,
'floorplans_1_title' => 'title xx',
'floorplans_1_house_area' => '90m²',
'floorplans_1_bedrooms' => '2',
'floorplans_2_valid_for_export' => 1,
'floorplans_2_title' => 'title 2',
'floorplans_2_house_area' => '50m²',
'floorplans_2_bedrooms' => 1,
)
With that constructed data it might be hard (not impossble tho), hovewer i would suggest to change it to multidimensional arrays so you have something like:
[floorplans][0][valid_for_export] => 0
[floorplans][0][title] => title 1
[floorplans][0][house_area] => 40m²
[floorplans][0][bedrooms] => 1
[floorplans][1][valid_for_export] => 1
[floorplans][1][title] => title xx
[floorplans][1][house_area] => 90m²
Rought sollution
It is not the best approach, but it should work if you dont need anything fancy, and know that structure of data wont change in future
$keys = [];
$for($i=0;$i<$array['floorplans'];++$i) {
if(isset($array['floorplans_'.$i.'_valid_for_export']) && $array['floorplans_'.$i.'_valid_for_export']===1) {
$keys[] = $i;
}
}
print_r($keys);
(In between Christmas meals) I am again stuck with the loop through array and group by logic.
here is the array I am given
$aTest = Array
(
Array
(
'date' => 2017-05-04,
'period' => 'period2',
'category' => 'Indoor room',
'score' => 1
),
Array
(
'date' => 2017-05-04,
'period' => 'period5',
'category' => 'Indoor room',
'score' => 1
),
Array
(
'date' => 2017-05-04,
'period' => 'period2',
'category' => 'Indoor room',
'score' => 2
),
Array
(
'date' => 2017-05-04,
'period' => 'period4',
'category' => 'Indoor room',
'score' => 1
),
Array
(
'date' => 2017-05-03,
'period' => 'period5',
'category' => 'Gym Class',
'score' => 1
),
Array
(
'date' => 2017-05-03,
'period' => 'period1',
'category' => 'Gym Class',
'score' => 1
),
Array
(
'date' => 2017-05-03,
'period' => 'period4',
'category' => 'Indoor room',
'score' => 1
)
);
This time I like group by category and sum the score group by period. Y-axis will be the category and X-axis will be the period. In the end I need this for a google chart
/*period, total indoor, total gym, 'total indoor', 'total gym'*/
array(
['Period1', 0,1,'0','1'],
['Period2', 3,0,'3','0'],
['Period3', 0, 0,'0','0'],
['Period4', 4,0,'4','0'],
['Period5', 1,1,'1','1']
)
I have this php code:
foreach ($aTest as $value) {
//echo $value['period'].' - '.$value['score'].'<br/>';
if (empty($output[$value]['period']))
$output[$value]['period'] = ['Period1' => 0, 'Period2' => 0, 'Period3' =>0, 'Period4' => 0, 'Period5' => 0];
if(empty($output[$value]['category']))
$output[$value['catgeory']] = ['Gym Class' => 0, 'Indoor room' =>0];
$output[$value['category']] += $value['score'];
}
ksort($output);
but this only totals the score by Category and not by period.
I think I need to loop through the periods as well, but how?
You have a wrong logic here.
if (empty($output[$value]['period']))
$output[$value]['period'] = ['Period1' => 0, 'Period2' => 0, 'Period3' =>0, 'Period4' => 0, 'Period5' => 0];
that $value is an array and you try to check $output[$value]
I saw that you don't have any line sum periods Value.
I have a solution for your data.
What is my code do??
Sum score of the period by the category
For each merge period and category score to an array using arraySort category to set position of these category scores values
$temp = [];
$output = [];
foreach($aTest as $value){
$period = $value['period'];
$category = $value['category'];
// Create default values
if (empty($temp[$period])){
$temp[$period] = [];
}
if(empty($temp[$period][$category])){
$temp[$period][$category] = 0;
}
//Sum score
$temp[$period][$category] += $value['score'];
}
//After Forech we have an array with ['period name' => ['category name' => score]];
//Sort values of the category change it if you want, you can add more option such as (item type for add '' to values)
$arraySort = [
"Indoor room", //total indoor,
"Gym Class", // total gym,
"Indoor room", //'total indoor',
"Gym Class" //'total gym'
];
foreach($temp as $period => $catsScore){
$periodItem = [$period];
foreach($arraySort as $cat){
$periodItem[] = $catsScore;
}
$output[] = $periodItem;
}
I am trying to build multidimensional to get json but its getting little complex. Sure there is easier way to do this. Here is my code.
$rows = array();
$idx = 0;
$sql = "SELECT products, GROUP_CONCAT(title,',' ,price SEPARATOR ', ' ) prods FROM mylist GROUP BY products";
$query = mysqli_query($con, $sql);
while($row = mysqli_fetch_assoc($query)){
$rows[$idx]['products'] = $row['products'];
$title = explode(',',$row['prods']);
$rows[$idx]['prods'] = $title;
$idx++;
};
echo '<pre>' . var_export($rows, true) . '</pre>';
echo json_encode($rows);
It give me this result
array (
0 =>
array (
'prods' =>
array (
0 => 'title 4',
1 => '4',
2 => ' title 1',
3 => '1',
),
),
1 =>
array (
'prods' =>
array (
0 => 'title 2',
1 => '21',
),
),
2 =>
array (
'prods' =>
array (
0 => 'title 3',
1 => '3',
),
),
)
[{"prods":["title 4","4"," title 1","1"]},{"prods":["title 2","21"]},{"prods":["title 3","3"]}]
But I want like this
array (
0 =>
array (
'prods' =>
array (
array(title => 'title 4', price => '4'),
array(title => ' title 1', price => '1'),
),
),
1 =>
array (
'prods' =>
array (
array(title => 'title 2', price => '21'),
),
),
2 =>
array (
'prods' =>
array (
array(title => 'title 3', price => '3'),
),
),
)
[
{
"prods": [
{
"title": "title 4",
"price": "4"
},
{
"title": "title1",
"price": "1"
}
]
},
{
"prods": [
{
"title": "title2",
"price": "21"
}
]
},
{
"prods": [
{
"title": "title3",
"price": "3"
}
]
}
]
So, not sure how to mix the exploded data on array to get the right json encoded.
You can do a foreach on the $title array and if the key is even then build the output array with the desired keys. In the below I edited to substituted your db query for json so that the full example can be included without the sql query.
$rows = array();
$idx = 0;
$data = json_decode('[{"products":"the product", "prods":"title 4,4,title 1,1"},{"products":"the product", "prods":"title 2,21"},{"products":"the product", "prods":"title 3,3"}]', true);
foreach ($data as $row)
{
$rows[$idx]['products'] = $row['products'];
$title = explode(',',$row['prods']);
foreach ($title as $k => $v) {
// check if even
if ($k % 2 == 0) $rows[$idx]['prods'][] = array('title' => $v, 'price' => $title[$k+1]);
}
$idx++;
};
echo '<pre>' . var_export($rows, true) . '</pre>';
echo json_encode($rows);
Will output the following
array (
0 =>
array (
'products' => 'the product',
'prods' =>
array (
0 => array ('title' => 'title 4','price' => '4'),
1 => array ('title' => 'title 1','price' => '1'),
),
),
1 =>
array (
'products' => 'the product',
'prods' =>
array (
0 => array ('title' => 'title 2','price' => '21'),
),
),
2 =>
array (
'products' => 'the product',
'prods' =>
array (
0 => array ('title' => 'title 3','price' => '3'),
),
),
)
Based on Tristan earlier suggestion, I was able to get the expected result with below code, not sure if that's the best way.
$rows = array();
$idx = 0;
$sql = "SELECT products, GROUP_CONCAT(title,',',price SEPARATOR ';') prods FROM mylist GROUP BY products";
$query = mysqli_query($con, $sql);
while($row = mysqli_fetch_assoc($query)){
$prods = explode(';',$row['prods']);
foreach ($prods as $key => $value) {
$expValue = explode(',',$value);
$rows[$idx]['prods'][] = array('title' => $expValue[0], 'price' => $expValue[1]);
};
$idx++;
};
echo '<pre>' . var_export($rows, true) . '</pre>';
echo json_encode($rows);
I have a requirement to allow my end users to input formula much like a spreadsheet. I have an array like this:
$table = array(
1=>array(
"id"=>1,
"Name"=>"Regulating",
"Quantity"=>"[2]Quantity+[3]Value",
"Value"=>"[2]Cost"
),
...)
The first level array key is always the same value as the id key in that array.
A tabulated example follows:
id Name Quantity Value
1 Regulating [2]Quantity+[3]Value [2]Cost
2 Kerbs 3 6
3 Bricks 9 7
4 Sausages [3]Cost 3
5 Bamboo [4]Quantity [7]Cost
6 Clams [4]Quantity NULL
7 Hardcore [3]Quantity*0.5 12
8 Beetles [6]Quantity*[4]Value [2]Value
The Quantity and Value keys represent formula which reference the [id] and either Quantity, Value or Cost.
Cost is derived by multiplying the Value and Quantity.
I am using:
preg_match_all("/\[(.*?)\]([A-Z]*[a-z]*)/", $string, $matches, PREG_SET_ORDER);
which outputs an array like so for[1][Quantity]:
Array
(
[0] => Array
(
[0] => [2]Quantity
[1] => 2
[2] => Quantity
)
[1] => Array
(
[0] => [3]Value
[1] => 3
[2] => Value
)
)
Iterating through the table using something similar to:
$calcString = $table[1]['Quantity'];`
foreach ($matches as $match) {
$calcString = str_replace($match[0], $table[$match[1]][$match[2]], $calcString);
}
I can get the string to be calculated and am using a matheval class to do the sum.
For example
[1]Quantity = [2]Quantity + [3]Value
[2]Quantity = 3
[3]Value = 7 // [1]Quantity = 3 + 7 = 10
[1]Value = [2]Cost
[2]Cost = [2]Quantity * [2]Value // 3 * 6 = 18
Basically the variables in the table refer to other [id]key in the same table.
But here is my issue
I need to resolve references to other parts of the table (which may or may not themselves be formula) to fill in the blanks. This is outside my comfort zone and I would appreciate any advice (or even better functional code) which provides enlightenment on how I might be able to achieve this.
Thanks
Deep down, you already know how to solve this, you're just intimidated by the task.
A recursive approach would be to expand references instantly. For example,
expand('[1]Value') # returns '[2]Cost'
expand('[2]Cost') # returns '[2]Quantity * [2]Value'
expand('[2]Quantity') # returns 3
expand('[2]Value') # returns 6
eval('3 * 6')
# returns 18
# returns 18
# returns 18
An iterative (non-recursive) approach is to expand one reference at a time and repeat until there are unresolved references in the string.
expand('[1]Value') // returns '[2]Cost'
expand('[2]Cost') // returns '[2]Quantity + [2]Value'
expand('[2]Quantity + [2]Value') // returns 3 for [2]Quantity
expand('3 * [2]Value') // returns 6 for [2]Value
eval('3 * 6')
# returns 18
Normally, I prefer iterative solutions, because they're much less prone to stack overflows. However, recursive solutions are usually easier to write.
Here's a quickly slapped-together recursive evaluator: https://gist.github.com/stulentsev/b270bce4be67bc1a96ae (written in ruby, though)
If calcString's are reasonably sized and you don't expect replacements to get too elaborate, you could use a while loop to simulate the recursion. Here's an example that outputs the string along the way as it is being modified:
$calcString = $table[8]['Quantity'];
preg_match_all("/\[(.*?)\]([A-Z]*[a-z]*)/", $calcString, $matches, PREG_SET_ORDER);
print_r($calcString . "\n");
while (!empty($matches)){
foreach ($matches as $match) {
preg_match_all("/\[(.*?)\](Cost)/", $match[0], $matchCost, PREG_SET_ORDER);
if (!empty($matchCost)){
$cost = $table[$matchCost[0][1]]['Quantity'] . "*" . $table[$matchCost[0][1]]['Value'];
$calcString = str_replace($match[0], $cost, $calcString);
} else {
$calcString = str_replace($match[0], $table[$match[1]][$match[2]], $calcString);
}
print_r($calcString . "\n");
}
preg_match_all("/\[(.*?)\]([A-Z]*[a-z]*)/", $calcString, $matches, PREG_SET_ORDER);
}
Output:
[6]Quantity*[4]Value
[4]Quantity*[4]Value
[4]Quantity*3
[3]Cost*3
9*7*3
The table variable:
$table = array(
1 => array(
"id" => 1,
"Name" => "Regulating",
"Quantity" => "[2]Quantity+[3]Value",
"Value" => "[2]Cost"
),
2 => array(
"id" => 2,
"Name" => "Kerbs",
"Quantity" => 3,
"Value" => 6
),
3 => array(
"id" => 3,
"Name"=>"Bricks",
"Quantity"=> 9,
"Value"=> 7
),
4 => array(
"id" => 2,
"Name" => "Sausages",
"Quantity" => "[3]Cost",
"Value" => 3
),
5 => array(
"id" => 2,
"Name" => "Bamboo",
"Quantity" => "[4]Quantity",
"Value" => "[7]Cost"
),
6 => array(
"id" => 2,
"Name" => "Clams",
"Quantity" => "[4]Quantity",
"Value" => NULL
),
7 => array(
"id" => 2,
"Name" => "Hardcore",
"Quantity" => "[3]Quantity*0.5",
"Value" => 12
),
8 => array(
"id" => 2,
"Name" => "Beetles",
"Quantity" => "[6]Quantity*[4]Value",
"Value" => "[2]Value"
)
);
A dangerously easy, and your-situation-specific well-performable solution!
<?php
class solver {
private
// The final output array
$arr_evaled,
// When a cell gains its final value, the corresponding entry in the following array gets marked as being done!
$arr_done;
private $solving_iterations_count;
public function solver($array) {
$this->arr_done = array();
foreach($array as $k => $arr)
$this->arr_done[$k] = array('Quantity' => false, 'Value' => false);
// Firstly,expand all of the "[x]Cost"s to "([x]Quantity*[x]Value)"s!
$this->arr_evaled = array_map(
function($v){ return preg_replace('#\[(\d*?)\]Cost#', '([$1]Quantity*[$1]Value)', $v); },
$array
);
$this->solving_iterations_count = 0;
$this->solve();
}
private function isDone() {
foreach($this->arr_done as $a)
if($a['Quantity'] == false || $a['Value'] == false)
return false;
return true;
}
private function isCellDone($id, $fieldName) {
return $this->arr_done[$id][$fieldName];
}
private function markCellAsDone($id, $fieldName, $evaluation) {
$this->arr_done[$id][$fieldName] = true;
$this->arr_evaled[$id][$fieldName] = $evaluation;
}
private function isEvaluable($str) {
return preg_match('#^[0-9*+-\/\(\)\.]*$#', $str) == 1 || strtolower($str)=='null';
}
private function replace($from, $to) {
foreach($this->arr_evaled as &$arr) {
$arr['Quantity'] = str_replace($from, $to, $arr['Quantity']);
$arr['Value'] = str_replace($from, $to, $arr['Value']);
}
}
private function solve() {
$isSolvable = true; // YOUR TODO: I believe coding this part is also fun!) (e.g: check for "reference cycles")
if(!$isSolvable) return null;
while( !$this->isDone() )
{
foreach($this->arr_evaled as $arr) {
foreach(['Quantity', 'Value'] as $fieldName) {
if(!$this->isCellDone($arr['id'], $fieldName)) {
if($this->isEvaluable($arr[$fieldName])) {
$evaluation = eval("return {$arr[$fieldName]};");
$this->markCellAsDone($arr['id'], $fieldName, $evaluation);
$this->replace("[{$arr['id']}]$fieldName", "$evaluation");
}
}
}
}
$this->solving_iterations_count++;
}
foreach($this->arr_evaled as &$row)
$row['Cost'] = $row['Quantity'] * $row['Value'];
return $this->arr_evaled;
}
public function print_tabulated() {
echo "The count of solving iterations: {$this->solving_iterations_count}<br/><br/>";
echo '<table border="1"><tr><th>id</th><th>Name</th><th>Quantity</th><th>Value</th><th>Cost</th></tr>';
foreach($this->arr_evaled as $arr)
echo "<tr><td>{$arr['id']}</td><td>{$arr['Name']}</td><td>{$arr['Quantity']}</td><td>{$arr['Value']}</td><td>{$arr['Cost']}</td></tr>";
echo '</table>';
}
}
// Testing
$arr = array(
1 => array( 'id' => 1, 'Name' => 'Regulating', 'Quantity' => '[2]Quantity+[3]Value', 'Value' => '[2]Cost' ),
2 => array( 'id' => 2, 'Name' => 'Kerbs', 'Quantity' => '3', 'Value' => '6' ),
3 => array( 'id' => 3, 'Name' => 'Bricks', 'Quantity' => '9', 'Value' => '7' ),
4 => array( 'id' => 4, 'Name' => 'Sausages', 'Quantity' => '[3]Cost', 'Value' => '3' ),
5 => array( 'id' => 5, 'Name' => 'Bamboo', 'Quantity' => '[4]Quantity', 'Value' => '[7]Cost' ),
6 => array( 'id' => 6, 'Name' => 'Clams', 'Quantity' => '[4]Quantity', 'Value' => 'NULL' ),
7 => array( 'id' => 7, 'Name' => 'Hardcore', 'Quantity' => '[3]Quantity*0.5', 'Value' => '12' ),
8 => array( 'id' => 8, 'Name' => 'Beetles', 'Quantity' => '[6]Quantity*[4]Value', 'Value' => '[2]Value' ),
);
echo '<pre>';
(new solver($arr))->print_tabulated();
Here is the output:
New to PHP and after spending hours researching on here, nothing seems to be exactly what I need. I have a multi dimensional array that I'm looking to pull data and COUNT from. FOR Instance:
array (
'loyola' => NULL,
'gold_coast' => NULL,
'lincolnpark' =>
array (
0 => 'Building 1',
1 => 'Building 2',
2 => 'Building 3',
3 => 'Building 4'
),
'lakeview' =>
array (
0 => 'Building 1',
1 => 'Building 2',
2 => 'Building 3'
),
)
I'm looking to essentially create a table that lists all the buildings and in the next column the number of times that building appears.
This what I've gotten thus far, but it only displays all buildings.
$buildings = unserialize($row['buildings']);
$lincolnpark = $buildings['lincolnpark'];
$loyola= $buildings['loyola'];
$gold_coast = $buildings['gold_coast'];
$lakeview = $buildings['lakeview'];
foreach ($lakeview as $value)
{
echo $value;
}
}
Try the code below. It will navigate recursively into the array and will print the qtd each build appear.
<?php
$arr = array (
'loyola' => NULL,
'gold_coast' => NULL,
'lincolnpark' =>
array (
0 => 'Building 1',
1 => 'Building 2',
2 => 'Building 3',
3 => 'Building 4'
),
'lakeview' =>
array (
0 => 'Building 1',
1 => 'Building 2',
2 => 'Building 3'
),
);
$ret = array();
countBuildings($arr);
foreach($ret as $key=>$value){
echo "Building: $key ==> qtd : $value <br>";
}
function countBuildings($arr = array()){
global $ret;
foreach($arr as $value){
if(is_array($value)){
countBuildings($value);
}else{
if($value != NULL){
if(isset($ret[$value])){
$ret[$value] += 1;
}else{
$ret[$value] = 1;
}
}
}
}
}
Do it in two passes: one for counting building occurrences in a separate array, and another for output.