Merge two multidimensional arrays into one in Php - php

Hi I have two multidimensional arrays in PhP and I am trying to create a new array which is flatter.
The first array is called weeksBooked and has a structure like below:
Array
(
[0] => Array
(
[periodweekno] => 27
)
[1] => Array
(
[periodweekno] => 28
)
[2] => Array
(
[periodweekno] => 29
)
)
The second one is called bookings . This stores the day a child was booked for that particular week.
Array
(
[0] => Array
(
[periodDayName] => Monday
)
[1] => Array
(
[periodDayName] => Tuesday
)
[2] => Array
(
[periodDayName] => Thursday
)
[3] => Array
(
[periodDayName] => Friday
)
)
I am trying to merge both the arrays and check if the perioddayName is Monday then in the "new" merged array I can show it as "monday"=> 0 and if not then show it as "monday"=> 1. I would like to repeat it for each "workday (i.e. monday - friday).
I apologise in advance if I am not explaining it well but this is what I am trying to achieve is a structure that I can bind to a table:
{Weekno:27, Monday:1,Tuesday:0,Wednedsay:1,Thursday:1,Friday:0
Weekno:28, Monday:0,Tuesday:0,Wednesday:1, Thursday:0,Friday:1}
This is my attempt so far but I just can't get it to flatten it :
$result = array();
foreach ($weeksbooked as $week) {
$sql = "SELECT periodDayName FROM Attendance WHERE weekno = ". $week['periodweekno'];
$bookings = $this->db->RawQuery($sql,null);
// print_r($bookings);
foreach ($bookings as $booking) {
$daysbooked= array();
if($booking['periodDayName'] == 'Monday'){
$daysbooked['monday'] = 0;
}else{
$daysbooked['monday'] = 1;
}
if($booking['periodDayName'] == 'Tuesday'){
$daysbooked['tuesday'] = 0;
}else{
$daysbooked['tuesday'] = 1;
}
.....
array_push($weeksbooked,$daysbooked)
}
array_push($result,$weekbooked)

Perhaps something like this?
$result = array();
foreach ($weeksbooked as $week) {
$sql = "SELECT periodDayName FROM Attendance WHERE weekno = ". $week['periodweekno'];
$bookings = $this->db->RawQuery($sql,null);
// print_r($bookings);
$thisweek = array('Weekno' => $week['periodweekno'],
'Monday' => 0,
'Tuesday' => 0,
'Wednesday' => 0,
'Thursday' => 0,
'Friday' => 0
);
foreach ($bookings as $booking) {
$thisweek[$booking['periodDayName']] = 1;
}
$result[] = $thisweek;
}
print_r($result);
It should produce an output something like what you are looking for. Without the raw data in a table it's hard to be certain.

Related

Sum the value of single array based on key value

This question is not a duplicate of other. it is different,This is current code, I am trying to sum the values of a array based on the same key value of date.
foreach ($TablesArr as $tr) {
$criteria = new CDbCriteria;
$criteria->select = 'date,mal';
$Arr1 = $tr::model()->findAll($criteria);
$array_1 = array();
foreach ($Arr1 as $a1) {
$array_1['date'] = $a1['date'];
$array_1['mal'] = $a1['mal'];
}
}
My Current output is:
Array
(
[date] => 2015-11-00
[mal] => 35
)
Array
(
[date] => 2015-12-00
[mal] => 20
)
Array
(
[date] => 2016-01-00
[mal] => 30
)
Array
(
[date] => 2016-01-00
[mal] => 10
)
Array
(
[date] => 2015-11-00
[mal] => 50
)
If the date is same, then sum the value of mal in the array. For example, In the above array, the date 2015-11-00 appears twice or more than twice (5 or 10 times etc) then sum all of the values of it for that date. Currently it appears twice so for 2015-11-00 the mal values will be 35+50=85. I want my output to be like this below:
Array
(
[date] => 2015-11-00
[mal] => 85
)
Array
(
[date] => 2015-12-00
[mal] => 20
)
Array
(
[date] => 2016-01-00
[mal] => 40
)
I have tried:
$result = array();
foreach($Arr1 as $data) {
$result[ $data['date'] ] += $data['mal'];
}
Your $array_1 variable doesn't contain all the values from the original $Arr1 array. You're overwriting the same elements each time through the loop, so it just contains the last item from $Arr1. These lines:
$array_1['date'] = $a1['date'];
$array_1['mal'] = $a1['mal'];
should be:
$array_1[] = array('date' => $a1['date'], 'mal' => $a1['mal']);
Another problem is that you're resetting $array_1 each time through the outer loop.
You can also use array_merge to combine the arrays, instead of the loop:
$array_1 = array();
foreach ($TablesArr as $tr) {
$criteria = new CDbCriteria;
$criteria->select = 'date,mal';
$Arr1 = $tr::model()->findAll($criteria);
$array_1 = array_merge($array_1, $Arr1);
}
You can use one of the solutions in php group by SUM using multi dimensional array to create an associative array with the sums grouped by date. You can turn this into a 2-dimensional array with another loop:
$newresult = array();
foreach ($result as $date => $mal) {
$newresult[] = array('date' => $date, 'mal' => $mal);
}
DEMO

Sorting Multidimensional Associative Array with 2 custom criteria: (Meals by Day of Week and Meal Time)

I have a multidimensional array which needs to be sorted by two custom criteria in order:
Day of Week
Meal of Day (breakfast/lunch/dinner)
Documentation of array_multisort() and uksort() have gotten me half way there each, but I am unable to put it all together meaningfully. Thank you for your time
Array
(
[name] => hashbrowns
[day] => monday
[mealTime] => breakfast
)
Array
(
[name] => Steak
[day] => monday
[mealTime] => dinner
)
Array
(
[name] => Avacados
[day] => tuesday
[mealTime] => dinner
)
Array
(
[name] => Peaches
[day] => tuesday
[mealTime] => lunch
)
Array
(
[name] => Sammich
[day] => monday
[mealTime] => lunch
)
Array
(
[name] => Kale & Sadness
[day] => tuesday
[mealTime] => breakfast
)
Desired output example:
Array
(
[name] => hashbrowns
[day] => monday
[mealTime] => breakfast
)
Array
(
[name] => Sammich
[day] => monday
[mealTime] => lunch
)
Array
(
[name] => Steak
[day] => monday
[mealTime] => dinner
)
Array
(
[name] => Kale & Sadness
[day] => tuesday
[mealTime] => breakfast
)
Array
(
[name] => Peaches
[day] => tuesday
[mealTime] => lunch
)
Array
(
[name] => Avacados
[day] => tuesday
[mealTime] => dinner
)
try this solution. Surely it can be done with php functions but what happened to you seems to work.
$data = array(
array("name" => "Otra cosa","day" => "thursday","mealTime" => "dinner"),
array("name" => "hashbrowns","day" => "monday","mealTime" => "breakfast"),
array("name" => "Steak","day" => "monday","mealTime" => "dinner"),
array("name" => "Avacados","day" => "tuesday","mealTime" => "dinner"),
array("name" => "Cuchu","day" => "monday","mealTime" => "breakfast"),
array("name" => "Avacados 2","day" => "monday","mealTime" => "lunch"));
$day = array("monday" => 0, "tuesday" => 1, "wednesday" => 2, "thursday" => 3, "friday" => 4, "saturday" => 5, "sunday" => 6);
$mealTime = array("breakfast" =>0, "lunch" =>1, "dinner" => 2);
$result = array();
foreach($data as $values) {
$d = $day[$values["day"]];
$mt = $mealTime[$values["mealTime"]];
if(!isset($result[$d])) {
$result[$d] = array();
}
if(!isset($result[$d][$mt])) {
$result[$d][$mt] = array();
}
$result[$d][$mt][] = $values;
ksort($result[$d]);
}
ksort($result);
$_result = array();
foreach($result as $r) {
foreach($r as $_r) {
foreach($_r as $__r) {
$_result[] = $__r;
}
}
}
return $_result;
//print_r("<pre>");
//print_r($_result);
//print_r("</pre>");
Very interesting question!
I have tried to abstract from it to create a generic function to order a multidimensional array by given array of criteria.
The result is the function below, which has as first parameter a multidimensional array like that provided in the question, and as second parameter a multidimensional array of associative arrays, each with the key to be sorted as key (i.e. 'day') and the desired sorted values as values (i.e. 'monday','tuesday',...). You can pass one, two or more criteria. If a row don't match the criteria, is appended at the end of resulting array; same if a row has the key criteria but their value is not in the criteria values (i.e. has the key='day' with value='everyday').
So, in your case, you have to do in this way:
$menu = //Your array//
$criteria = array
(
'day' => explode( ',', 'monday,tuesday,wednesday,thursday,friday,saturday,sunday' ),
'mealTime' => explode( ',', 'breakfast,lunch,dinner' )
);
$result = sortArrayByCriteria( $menu, $criteria );
You can see the result in this eval.in demo (I have added to your array a fake item to see the behavior when there is a non-matching criteria).
The function:
/* Sort a multidimensional array by an array of criteria which keys are
* the key to sort and values are the sort criteria
* Unmatched values are appended at the end of array.
*
* #param array $array array to be sorted
* #param array $criteria array of criteria
*
* #return array sorted array
*/
function sortArrayByCriteria( $array, $criteria )
{
# Extract current (last) criteria and reduce criteria array:
$sortValues = end( $criteria );
$sortKey = key( $criteria );
array_pop( $criteria );
$sorted = $unsorted = array();
foreach( $sortValues as $compare )
{
$key = 0;
# Check each array:
while( $key < count( $array ) )
{
# If array row doesn't have key to sort, add-it to unsorted array:
if( !isset($array[$key][$sortKey]) )
{ $unsorted[] = reset( array_splice( $array, $key, 1 ) ); }
else
{
# If value==current comparisation value, add-it to sorted:
if( $array[$key][$sortKey] == $compare )
{ $sorted[] = reset( array_splice( $array, $key, 1 ) ); }
# If value doesn't is in the comparisation values, add-it to unsorted:
elseif( !in_array( $array[$key][$sortKey], $sortValues ) )
{ $unsorted[] = reset( array_splice( $array, $key, 1 ) ); }
# Otherwise increment index pointer:
else $key++;
}
}
}
# Merge sorted and unsorted values in one array:
$retval = array_merge( $sorted, $unsorted );
# If there are others criteria, performs a self-call:
if( count( $criteria ) ) $retval = sortArrayByCriteria( $retval, $criteria );
return $retval;
}
Consider simply adding mealnumber and daynumber to main array, sort by those numeric fields using array_multisort() and then remove them from array:
// INITIALIZE SORT ARRAYS
$mealarr = array();
$dayarr = array();
// APPEND TO MAIN AND SORT ARRAYS, NEW MEALNUMEBR AND DAYNUMBER ELEMENTS
for($i=0; $i<sizeof($breakfast); $i++){
foreach ($breakfast[$i] as $key => $value) {
switch ($value) {
case "breakfast": $breakfast[$i]['mealnumber'] = 1; $mealarr[] = 1; break;
case "lunch": $breakfast[$i]['mealnumber'] = 2; $mealarr[] = 2; break;
case "dinner": $breakfast[$i]['mealnumber'] = 3; $mealarr[] = 3; break;
case "monday": $breakfast[$i]['daynumber'] = 1; $dayarr[] = 1; break;
case "tuesday": $breakfast[$i]['daynumber'] = 2; $dayarr[] = 2; break;
case "wednesday": $breakfast[$i]['daynumber'] = 3; $dayarr[] = 3; break;
case "thursday": $breakfast[$i]['daynumber'] = 4; $dayarr[] = 4; break;
case "friday": $breakfast[$i]['daynumber'] = 5; $dayarr[] = 5; break;
case "saturday": $breakfast[$i]['daynumber'] = 6; $dayarr[] = 6; break;
case "sunday": $breakfast[$i]['daynumber'] = 7; $dayarr[] = 7; break;
}
}
}
// SORT MAIN ARRAY
array_multisort($dayarr, SORT_ASC, $mealarr, SORT_ASC, $data);
// REMOVE MEALNUMBER AND DAYNUMBER ELEMENTS
for($i=0; $i<sizeof($data); $i++){
foreach ($data[$i] as $key => $value) {
if ($key=='mealnumber' or $key=='daynumber') {
unset($data[$i][$key]);
}
}
}

put values from query into array

I need values from my database to plot a graph.
I have multiple lines I want to plot on the same graph.
I need the values, for each line, in the following form, for as many different $dates there are in the database:
$graph_points1 = array(array($date, $value), array($date, $value), array($date, $value));
I have a query to get the data from the database:
$data = $wpdb->get_results($wpdb->prepare( "SELECT * FROM `wp_graph_info` ORDER BY DATE ASC"));
If I use the following code:
foreach($data as $datas){
$list_name = $datas->list_name;
$date = $datas->date;
$value = $datas->subscriber_count;
if($list_name == 'line1'){
$result = array(array($date,$value));}}
print_r($result); will give:
Array ( [0] => Array ( [0] => 2015-05-16 [1] => 131 ) )
Array ( [0] => Array ( [0] => 2015-05-17 [1] => 133 ) )
Array ( [0] => Array ( [0] => 2015-05-18 [1] => 137 ) )
which is almost what I want.
I need to have the results as:
$graph_points1 = array(array(2015-05-16, 131), array(2015-05-17, 133), array(2015-05-18, 137));
how to I put it in the above form?
Also I can't plot the date on the x-axis. How do I only retrieve the 'day' value so I have:
$graph_points1 = array(array(16, 131), array(17, 133), array(18, 137));
Also if there a way to loop through all th $list_names (I have 7 different lists, so my graph will plot 7 lines) or do I need to use an if() statement for each one?
$result = [];
foreach($data as $datas){
$list_name = $datas->list_name;
$date = $datas->date;
$value = $datas->subscriber_count;
list($year, $month, $day) = explode('-', $date);
$result[$list_name][] = array($day,$value);
}
echo "<pre>";var_dump($result);echo "</pre>";

Array values replaced rather than pushed

I'm trying to build a multidimensional array like array(years => array(months)). Each new month added to a year replaces the old month value in the year array rather than appending the value.
<?php
$dates = array();
foreach (Blog::all() as $blog) {
$date_year = date("Y", strtotime($blog->created_at));
$date_month = date("F", strtotime($blog->created_at));
if (!in_array($date_year, $dates)) {
$dates[$date_year] = array();
}
if (!in_array($date_month, $dates[$date_year])) {
$dates[$date_year][] = $date_month;
print $date_year." ".$date_month."<br>";
}
}
print_r($dates); ?>
Outputs:
Array ( [2009] => Array ( [0] => December ) [2010] => Array ( [0] => March ) [2011] => Array ( [0] => August ) [2012] => Array ( [0] => November ) [2013] => Array ( [0] => October ) [2014] => Array ( [0] => April ) )
The months displayed are the last month available for each year. I have also tried with array_push($dates[$date_year], $date_month) for the same result.
The year array is being overwritten each time here:
if (!in_array($date_year, $dates)) {
$dates[$date_year] = array();
}
Check the array keys instead of the array values with array_key_exists:
if (!array_key_exists($date_year, $dates)) {
$dates[$date_year] = array();
}
Or, better yet IMO, use isset as suggested by vp_arth below. (For succintness.)
if (!isset($dates[$date_year])) {
$dates[$date_year] = array();
}

Grouping data and presenting in a table from an api

I am returning data in a for each loop in 2 strings from an api like this:
eg $key = "2012 q4"; and $value = "34542";
*2012 q4* **34542**
*2012 q3* **35383**
*2012 q2* **36171**
*2012 q1* **36926**
*2011 q4* **37913**
*2011 q3* **38740**
*2011 q2* **39641**
*2011 q1* **40548**
I would then like to display it in this format in a table
year q1 q2 q3 q4
2012 36926 36171 35383 34542
2011 40548 39641 38740 37913
This is all I have so far, literally clueless on how to go from here.
foreach($hm["quarterly_tax"]["licensed"] as $key => $value) {
echo $key." ".$value."<br />";
}
I could work out the year and quarter by doing this I guess:
$year = substr($key, 0, 4);
$quater = substr($key, 5, 7);
but stuck from then on...
Any help would be appreciated
Have not tested it, but should give you the some idea for the logic.
foreach($hm["quarterly_tax"]["licensed"] as $key => $value) {
$year = substr($key, 0, 4);
$quater = substr($key, 5, 7);
$arr[$year][$q][] = $value;
}
Now you will have an 3d array that's sorted per possible values, should be something like this : `
Array
(
[2012] => Array
(
[q1] => Array
(
[0] => 36926
[1] => 12345
)
[q2] => Array
(
[0] => 36171
)
[q3] => Array
(
[0] => 35383
)
)
[2011] = Array
(
[q1] = Array
(
[0] =40548
)
)
)
Which is much easier to handle, since it's sorted to the way you need it, now u can just output the table accordingly.

Categories