how to sum in a multidimensional array in php - php

As an example I have an array like this:
$Batches = array(
$Batch_1= array(
$A_Row= array(1,1,0,0),
$B_Row = array(0,0,0,1),
$C_Row = array(0,0,0,1)),
$Batch_2= array(
$A_Row= array(1,0,0,0),
$B_Row = array(0,0,0,1),
$C_Row = array(0,0,0,1))
);
I want to sum per each $n_Row:
So I should get a result like this:
$Sum_Array = array(
$A_row=array(2,1,0,0),
$B_row= array(0,0,0,2),
$C_row = array(0,0,0,2)
);
But I'm having difficulty trying to get this result and need some tips/advice from someone else.
This is my code so far:
//count rows and columns
$count_array= count($Batches);
$count_row = count($Batches[0]);
$count_column = count($Batches[0][0]);
$Array_sum = array();
for($array=0;$array<$count_array;$array++){
for($row=0;$row<$count_row;$row++){
for($col=0;$col<$count_column;$col++){
//echo $Batches[$array][$row][$col] . "\n";
if($Batches[$array][$row][$col]==1){
$Batches[$array][$row][$col]++;
}
$Array_sum[]=$Batches[$array][$row][$col];
}
}
}
Anyone who can help me in the right direction?
Thanks in advance.

I think your "array"
$Batches = array(
$Batch_1= array(
$A_Row= array(1,1,0,0),
$B_Row = array(0,0,0,1),
$C_Row = array(0,0,0,1)),
$Batch_2= array(
$A_Row= array(1,0,0,0),
$B_Row = array(0,0,0,1),
$C_Row = array(0,0,0,1))
);
is a product of the imagination. But it is also valid PHP code. I assume you want to work with keys and the array looks like this:
$Batches = array(
'Batch_1' => array(
'A_Row' => array(1,1,0,0),
'B_Row' => array(0,0,0,1),
'C_Row' => array(0,0,0,1)),
'Batch_2' => array(
'A_Row' => array(1,0,0,0),
'B_Row' => array(0,0,0,1),
'C_Row' => array(0,0,0,1))
);
The Summation works better with foreach.
$sum_arr = [];
foreach($Batches as $ib => $batch){
foreach($batch as $ir => $row){
foreach($row as $ic => $col){
$sum_arr[$ir][$ic] ??= 0;
$sum_arr[$ir][$ic] += $col;
}
}
}
var_export($sum_arr);
The Output:
array (
'A_Row' =>
array (
0 => 2,
1 => 1,
2 => 0,
3 => 0,
),
'B_Row' =>
array (
0 => 0,
1 => 0,
2 => 0,
3 => 2,
),
'C_Row' =>
array (
0 => 0,
1 => 0,
2 => 0,
3 => 2,
),
)
The summation also works with the original array. However, this array has only numeric keys.

Related

How to format html table to show unique months and item id and sum the cost? (PHP)

I have been stuck for days on this 'little' problem.
I have one array which contains specific data:
$data = array(
0 => array('id' => 8, 'month' => 1, 'cost' => 12500),
1 => array('id' => 8, 'month' => 2, 'cost' => 14200),
2 => array('id' => 9, 'month' => 1, 'cost' => 23000),
3 => array('id' => 9, 'month' => 2, 'cost' => 18000),
);
And this is the html table results i need to get:
Id Jan Feb Mar Apr May
8 12,500 14,200 10,200 10,300 11,000
9 23,000 18,000 21,320 10,642 14,636
How i can sort array to display this data in html table on view.ctp ?
I have tried using foreach loops but i really don't know how to put unique months and unique id like it is displayed above. I'm using CakePHP 2.x technology.
I appreciate every help. Thank you
Loop over your array and group into a new array based on the ID. Assign month=cost key-value pairs, using IDs as the grouping keys of your multidimensional array.
$by_id = [];
foreach($data as $x) {
$by_id[$x['id']][$x['month']] = $x['cost'];
// e.g. $by_id[8][2] = 14200;
}
This will turn your sample data into the following array:
array(2) {
[8] · array(2) {
[1] · int(12500)
[2] · int(14200)
}
[9] · array(2) {
[1] · int(23000)
[2] · int(18000)
}
}
That should be much easier to turn into a HTML table. For example like this:
$html = [];
$html[] = '<table>';
$html[] = '<tr><th>ID</th><th>Jan</th><th>Feb</th></tr>';
foreach($by_id as $id => $months) {
$html[] = '<tr>';
$html[] = "<td>{$id}</td>";
foreach($months as $month => $cost) {
$html[] = "<td>{$cost}</td>";
}
$html[] = '</tr>';
}
$html[] = '</table>';
echo implode("\n", $html);
I trust the code is clear enough without elaborate comments. Add months to the table header as necessary. Use e.g. number_format for $cost to format your monies. Be aware that the sample code above doesn't account for possible missing months for a given ID, it assumes symmetric data. Add checks and remedies if necessary. See demo at https://3v4l.org/7CFRf.
You should use a 2D array to display that kind of table.
Then the $data array might be like this:
$data = array(
0 => array('id' => 8, 'costData' => array(
0 => array('month' => 1, 'cost' => 12500),
1 => array('monnt' => 2, 'cost' => 14200)
),
1 => array('id' => 9, 'costData' => array(
0 => array('month' => 1, 'cost' => 23000),
1 => array('month' => 2, 'cost' => 18000)
)
);
To revert the $data array like this, the code below will be needed.
<?php
$newData = array();
for($i = 0; $i < count($data); $i++)
{
$newItem = array('id' => $data[$i]['id'], 'costData' => array(
'month' => $data[$i]['month'],
'cost' => $data[$i]['cost']
));
for($j = $i + 1; $j < count($data); $j++)
{
if($data[$j]['id'] == $data[$i]['id']) {
$newItem['costData'][] = array('month' => $data[$j]['month'], 'cost' => $data[$j]['cost']);
array_splice($data, $j, 1);
$j--;
}
}
$newData[] = $newItem;
}
Using new data Array, you can make your html page like this.
$html = '';
for($i = 0; $i < count($newData); $i++)
{
$html .= '<tr>';
$html .= '<td>'.($newData[$i]['id']).'</td>';
for($j = 0; $j < count($newData[$i]['costData']); $j++) {
$html .= '<td>'.($newData[$i]['costData'][$j]).'</td>';
// you can do some operations if there are missing months to leave blank td tags..
}
// fill the missing months to fill the td tags.
}
You could use a combination of the array_column() and array_sum() functions:
$data = array(
array('id' => 8, 'month' => 1, 'cost' => 12500),
array('id' => 8, 'month' => 2, 'cost' => 14200),
array('id' => 9, 'month' => 1, 'cost' => 23000),
array('id' => 9, 'month' => 2, 'cost' => 18000),
);
$result = array();
foreach ($data as $row) {
$result[$row['id']][$row['month']] = $row['cost'];
}
// Sum the costs for each month
$months = array_column($data, 'month');
$result = array_map(function($v) use ($months) {
return array_sum(array_intersect_key($v, array_flip($months)));
}, $result);
print_r($result);
This will output:
Array
(
[8] => Array
(
[1] => 12500
[2] => 14200
)
[9] => Array
(
[1] => 23000
[2] => 18000
)
)

Two while loops to single array?

I'm trying to take parts number from two different tables and put them in the same array, then rearrange them.
Strangely it gives parts number twice, but when I run the same query in phpmyadmin it gives each part number once. I spend whole day but could not correct this.
//first query
$finalData = array(); $sql="SELECT
jobc_parts_p.part_no,
SUM(jobc_parts_p.issued_qty) AS sale_qty FROM
`jobc_parts_p` WHERE DATE_FORMAT(jobc_parts_p.date_time,'%Y-%m-%d') BETWEEN '".$f."' AND '".$t."'
GROUP BY jobc_parts_p.part_no";
$result = $conn->query($sql);
while($row = $result->fetch_assoc()){
$finalData[$row['part_no']][] = $row;
}
//second query
$sql2="SELECT
jobc_consumble_p.part_no,
SUM(jobc_consumble_p.issued_qty) AS csale_qty
FROM
`jobc_consumble_p`
WHERE DATE_FORMAT(jobc_consumble_p.date_time,'%Y-%m-%d') BETWEEN '".$f."' AND '".$t."'
GROUP BY
jobc_consumble_p.part_no";
$result = $conn->query($sql);
while($row = $result->fetch_assoc()){
$finalData[$row['part_no']][] = $row;
}
/// rearanging data......
$rearrangedFinalData = array();
foreach($finalData AS $first) {
foreach($first AS $data) {
$temp = array();
$temp['part_no'] = $data['part_no'];
$temp['sale_qty'] = isset($data['sale_qty']) ? $data['sale_qty'] : $data['csale_qty'];
$rearrangedFinalData[] = $temp;
}
}
//output result
foreach($rearrangedFinalData AS $row) {
$sr++;
echo "<tr><td>$sr</td>
<td colspan='2' >",$row["part_no"],"</td>
<td align='center'>",$row["sale_qty"],"</td>
</tr>";
}
RESULT
1 10R46 2
2 10R46 2
3 10R91 1
4 10R91 1
5 10M95 3
6 10M95 3
What i want:
1 10R46 2
2 10R91 1
3 10M95 3
First query print_r($finalData);
Array (
[10R46 ] => Array ( [0] => Array ( [part_no] =>
10R46 [sale_qty] => 1 ) )
[10R91 ] => Array ( [0] => Array ( [part_no] =>
10R91 [sale_qty] => 3 ) ))
Because, you are looping twice:
Modify
$rearrangedFinalData = array();
foreach($finalData AS $first) {
foreach($first AS $data) { // <-- Remove this extra loop.
$temp = array();
$temp['part_no'] = $data['part_no'];
$temp['sale_qty'] = isset($data['sale_qty']) ? $data['sale_qty'] : $data['csale_qty'];
$rearrangedFinalData[] = $temp;
}
}
To:
$rearrangedFinalData = array();
foreach($finalData AS $first) {
$temp = array();
$temp['part_no'] = $first['part_no'];
$temp['sale_qty'] = isset($first['sale_qty']) ? $first['sale_qty'] : $data['csale_qty'];
$rearrangedFinalData[] = $temp;
}
I think your problem lies within the $finalData where you store same results twice. (ofcourse from different tables though).
the first query creates a result of
$finalData = array(
'10R46' => array(0 => array('part_no' => 10R46, 'sale_qty' => 2)),
'10R91' => array(0 => array('part_no' => 10R91, 'sale_qty' => 1)),
'10M95' => array(0 => array('part_no' => 10M95, 'sale_qty' => 2))
);
then you run the second query and ADD to the finaldata again with this $finalData[$row['part_no']][] = $row;
so the $finalData is now something like
$finalData = array(
'10R46' => array(0 => array('part_no' => 10R46, 'sale_qty' => 2), 1 => array('part_no' => 10R46, 'csale_qty' => 2)),
'10R91' => array(0 => array('part_no' => 10R91, 'sale_qty' => 1), 1 => array('part_no' => 10R91, 'csale_qty' => 1)),
'10M95' => array(0 => array('part_no' => 10M95, 'sale_qty' => 3), 1 => array('part_no' => 10M95, 'csale_qty' => 3))
);
That is the reason why you double loop it and also get double results.
So i would combine the queries.
$sql="SELECT
jobc_parts_p.part_no,
SUM(jobc_parts_p.issued_qty) AS sale_qty,
SUM(jobc_consumble_p.issued_qty) AS csale_qty ## this part was added
FROM `jobc_parts_p`
LEFT JOIN `jobc_consumable_p` ON (jobc_consumable_p.part_no = jobc_parts_p.part_no) ## this part was added
WHERE DATE_FORMAT(jobc_parts_p.date_time,'%Y-%m-%d') BETWEEN '".$f."' AND '".$t."'
GROUP BY jobc_parts_p.part_no";
and now your result should look something like this without the secondquery
$finalData = array(
'10R46' => array(0 => array('part_no' => 10R46, 'sale_qty' => 2, 'csale_qty' => 2)),
'10R91' => array(0 => array('part_no' => 10R91, 'sale_qty' => 1, 'csale_qty' => 1)),
'10M95' => array(0 => array('part_no' => 10M95, 'sale_qty' => 2, 'csale_qty' => 3))
);
also if you don't expect there would be two rows with same part_no you can change
$finalData[$row['part_no']][] = $row; -> $finalData[$row['part_no']] = $row;
So you don't need to double loop it.
$new_array = array_values(array_unique($rearrangedFinalData));
Remove the duplicates and rearrange the keys (if needed) before you put your array in the foreach.
Then you can use the $new_array to generate your html

How do I reform this array into a differently structured array

I have an array that looks like this:
[0] => Array
(
[name] => typeOfMusic
[value] => this_music_choice
)
[1] => Array
(
[name] => myMusicChoice
[value] => 9
)
[2] => Array
(
[name] => myMusicChoice
[value] => 8
)
I would like to reform this into something with roughly the following structure:
Array(
"typeOfMusic" => "this_music_choice",
"myMusicChoice" => array(9, 8)
)
I have written the following but it doesn't work:
foreach($originalArray as $key => $value) {
if( !empty($return[$value["name"]]) ){
$return[$value["name"]][] = $value["value"];
} else {
$return[$value["name"]] = $value["value"];
}
}
return $return;
I've tried lots of different combinations to try and get this working. My original array could contain several sets of keys that need converting to arrays (i.e. it's not always going to be just "myMusicChoice" that needs converting to an array) ?
I'm getting nowhere with this and would appreciate a little help. Many thanks.
You just need to loop over the data and create a new array with the name/value. If you see a repeat name, then change the value into an array.
Something like this:
$return = array();
foreach($originalArray as $data){
if(!isset($return[$data['name']])){
// This is the first time we've seen this name,
// it's not in $return, so let's add it
$return[$data['name']] = $data['value'];
}
elseif(!is_array($return[$data['name']])){
// We've seen this key before, but it's not already an array
// let's convert it to an array
$return[$data['name']] = array($return[$data['name']], $data['value']);
}
else{
// We've seen this key before, so let's just add to the array
$return[$data['name']][] = $data['value'];
}
}
DEMO: https://eval.in/173852
Here's a clean solution, which uses array_reduce
$a = [
[
'name' => 'typeOfMusic',
'value' => 'this_music_choice'
],
[
'name' => 'myMusicChoice',
'value' => 9
],
[
'name' => 'myMusicChoice',
'value' => 8
]
];
$r = array_reduce($a, function(&$array, $item){
// Has this key been initialized yet?
if (empty($array[$item['name']])) {
$array[$item['name']] = [];
}
$array[$item['name']][] = $item['value'];
return $array;
}, []);
$arr = array(
0 => array(
'name' => 'typeOfMusic',
'value' => 'this_music_choice'
),
1 => array(
'name' => 'myMusicChoice',
'value' => 9
),
2 => array(
'name' => 'myMusicChoice',
'value' => 8
)
);
$newArr = array();
$name = 'name';
$value = 'value';
$x = 0;
foreach($arr as $row) {
if ($x == 0) {
$newArr[$row[$$name]] = $row[$$value];
} else {
if (! is_array($newArr[$row[$$name]])) {
$newArr[$row[$$name]] = array();
}
array_push($newArr[$row[$$name]], $row[$$value]);
}
$x++;
}

Given this array, how can I reformat it to look like this

If I had an array:
$data = array(
array(
'manufacturers_id' => 29,
'manufacturers_name' => 'Quicksilver',
'products_quantity' => 1,
'products_price' => 15.6000,
'products_cost' => 8.0000,
),
array(
'manufacturers_id' => 29,
'manufacturers_name' => 'Quicksilver',
'products_quantity' => 2,
'products_price' => 4.6722,
'products_cost' => 2.4000,
)
);
How can I reformat this to provide the structure
Array
(
[Quiksilver] => Array
(
[brands_sales] => $brandsSalesVal
[brands_products_sold] => $brandsSoldVal
[brands_costs] => $brandsCostsVal
)
$brandsSalesVal = A sum of all the products_price * products_quantity (for each manufacturer_id)
$brandsSoldVal= A sum of all the products_quantity for each manufacturer
$brandsCostsVal= A sum of all the products_costs for each manufacturer
Any help is greatly appreciated and I am thankful for anyone to take time to answer my rather lengthy query. I am still getting to grips with reformating arrays.
You need to use a foreach loop like so:
// Declare the totals array and
// the manufacturers->id map
$totals = array();
$manufacturers = array();
// Loop through the array of products and populate
// the totals array
foreach($data as $value){
// Set the key to the manufacturers name
$key = $value['manufacturers_name'];
// If the array has not been built yet, then ensure the
// values are set to 0 and add the manufacturer to the
// manufacturers map if it is not already there
if(!isset($totals[$key])){
// Add the manufacturer to the map
$manufacturers[$value['manufacturers_id']] = $key;
// Default the values to 0
$totals[$key]['brand_sales'] = 0;
$totals[$key]['brands_products_sold'] = 0;
$totals[$key]['brands_costs'] = 0;
}
// Calculate the brand sales
$totals[$key]['brand_sales'] += ($value['products_price']*$value['products_quantity']);
// Calculate the brand sales
$totals[$key]['brands_products_sold'] += $value['products_quantity'];
// Calculate the brand sales
$totals[$key]['brands_costs'] += $value['products_cost'];
}
In order to access the information stored in the array generated above, you can use another foreach loop like so:
// Loop through the $totals array and print the result
foreach($totals as $key => $value){
// Print the manufacturers name and ID
echo "\n".$key." (ID: ".array_search($key,$manufacturers).")";
// Print the totals for the current manufacturer
echo "\n\tBrand Sales: ".$values['brand_sales'];
echo "\n\tBrand Products Sold: ".$values['brands_products_sold'];
echo "\n\tBrand Costs: ".$values['brands_costs'];
}
The array_search function is used to look up the ID of the manufacturer based on the manufacturers name stored in the $manufacturers array. You can alter the code so that it does not need the array_search function, but I have done it like this because traditionally you would map the ID->NAME, not NAME->ID. It is just personal preference...
For more information on the foreach loop, see here
$data = array(
array(
'manufacturers_id' => 29,
'manufacturers_name' => 'Quicksilver',
'products_quantity' => 1,
'products_price' => 15.6000,
'products_cost' => 8.0000,
),
array(
'manufacturers_id' => 29,
'manufacturers_name' => 'Quicksilver',
'products_quantity' => 2,
'products_price' => 4.6722,
'products_cost' => 2.4000,
)
,
array(
'manufacturers_id' => 30,
'manufacturers_name' => 'Different Brand',
'products_quantity' => 2,
'products_price' => 4.6722,
'products_cost' => 2.4000,
)
);
$sortedData = array();
foreach($data as $num => $row){
$manufacturersName = $row['manufacturers_name'];
//If we don't have an array made for the manufacturer yet, make one
if(!isset($sortedData[$manufacturersName])){
$sortedData[$manufacturersName] = array(
'brands_sales' => 0,
'brands_products_sold' => 0,
'brands_costs' => 0
);
};
//Make a reference to the relevant manufacturer sorted data
$manufacturerData = &$sortedData[$manufacturersName];
$qty = $row['products_quantity'];
//
$manufacturerData['brands_sales'] += $qty * $row['products_price'];
$manufacturerData['brands_products_sold'] += $qty;
$manufacturerData['brands_costs'] += $row['products_cost'];
}
var_dump($sortedData); // <- your result.
Result:
array (size=2)
'Quicksilver' =>
array (size=3)
'brands_sales' => float 24.9444
'brands_products_sold' => int 3
'brands_costs' => float 10.4
'Different Brand' =>
array (size=3)
'brands_sales' => float 9.3444
'brands_products_sold' => int 2
'brands_costs' => float 2.4

PHP: Merge arrays in loop

public function getCheckoutForm(){
$arr = array(
'cmd' => '_cart',
'business' => 'some#mail',
'no_shipping' => '1',
'upload' => '1',
'return' => 'url',
'cancel_return' => 'url1',
'no_note' => '1',
'currency_code' => 'url2',
'bn' => 'PP-BuyNowBF');
$cpt=1;
foreach($this->items as $item){
$arr1[] = array(
'item_number_'.$cpt.'' => $item['item_id'],
'item_name_'.$cpt.'' => $item['item_name'],
'quantity_'.$cpt.'' => $item['item_q'],
'amount_'.$cpt.'' => $item['item_price']
);
$cpt++;
}
return array_merge($arr,$arr1[0],$arr1[1]);
}
This returns array like that:
Array
(
[cmd] => _cart
[business] => some#mail
[no_shipping] => 1
[upload] => 1
[return] => url1
[cancel_return] =>url2
[no_note] => 1
[currency_code] => EUR
[bn] => PP-BuyNowBF
[item_number_1] => 28
[item_name_1] => item_name_1
[quantity_1] => 1
[amount_1] => 5
[item_number_2] => 27
[item_name_2] => item_name_2
[quantity_2] => 1
[amount_2] => 30
)
The problem is that in return $arr1[0] and $arr1[1] are hardcoded. And if in loop i have more than 2 arrays, lets say 0,1,2,3 ans so on, this code won't work. Any idea? Maybe my logic is compleatly wrong...
There's no need to create arrays in your loop - just add new keys directly to the first array:
public function getCheckoutForm(){
$arr = array(
'cmd' => '_cart',
'business' => 'some#mail',
'no_shipping' => '1',
'upload' => '1',
'return' => 'url',
'cancel_return' => 'url1',
'no_note' => '1',
'currency_code' => 'url2',
'bn' => 'PP-BuyNowBF'
);
$cpt=1;
foreach($this->items as $item){
$arr['item_number_'.$cpt] = $item['item_id'];
$arr['item_name_'.$cpt] = $item['item_name'];
$arr['quantity_'.$cpt] = $item['item_q'];
$arr['amount_'.$cpt] = $item['item_price'];
$cpt++;
}
return $arr;
}
I would probably do something like
$count = count($arr1);
for($i=0;$i<$count;$i++){
$arr = array_merge($arr,$arr1[$i]);
}
return $arr;
I hope, I understood, what you mean ^^
foreach ($i = 0, $n = count($arr1); $i < $n; $i++) {
$arr = array_merge($arr, $arr1[$i]);
}
return $arr;
You could do the merge in every iteration:
foreach($this->items as $item){
$temp_arr = array(
'item_number_'.$cpt.'' => $item['item_id'],
'item_name_'.$cpt.'' => $item['item_name'],
'quantity_'.$cpt.'' => $item['item_q'],
'amount_'.$cpt.'' => $item['item_price']
);
$arr = array_merge($arr,$temp_arr)
$cpt++;
}
which has the advantage that you could possibly get $temp_arr from a function,
or just add all the elements to one array:
foreach($this->items as $item){
$arr['item_number_'.$cpt.''] => $item['item_id'];
$arr['item_name_'.$cpt.''] => $item['item_name'];
$arr['quantity_'.$cpt.''] => $item['item_q'];
$arr['amount_'.$cpt.''] => $item['item_price'];
$cpt++;
}
do this
$count = count($data);
$sum = 1;
$arr = [];
for($i=0;$i<$count;$i++){
$temp = $arr;
if($i == $count - 1){
$sum = 0;
}
$arr = array_merge($temp,$data[$i + $sum]);
}
return $arr;

Categories