Draw a Google Chart with undefined number of lines - php

I need to draw a Google Chart with an undefined number of lines (rows). Lets suppose I need to draw the number of goals of two teams in a certain day (the number of teams is fixed for the example, but it could be anyone, the number of days are the same for all teams). I have this array:
Array
(
[team1] => Array
(
[0] => Array
(
[day] => 1
[goals] => 3
)
[1] => Array
(
[day] => 2
[goals] => 1
)
[2] => Array
(
[day] => 3
[goals] => 0
)
)
[team2] => Array
(
[0] => Array
(
[day] => 1
[goals] => 1
)
[1] => Array
(
[day] => 2
[goals] => 2
)
[2] => Array
(
[day] => 3
[goals] => 4
)
)
)
I have tried creating this loop:
$resultArray = array();
$resultArray['cols'][] = array('label' => "Day", 'type' => 'string');
// $array is the one shown before
foreach($array as $key => $chartData){
$resultArray['cols'][] = array('label' => $key, 'type' => 'number');
foreach($chartData as $data){
$resultArray['rows'][] = array('c' => array( array('v' => $data['day']), array('v' => $data['goals'])));
}
}
The problem is that the chart only draws one line with the data from both teams joined all together instead two lines one for each team.
I would really appreciate any help.

I think your making it harder on yourself using associative arrays for google chart data. The data structure of your array is also adding some challenges to the loop making it a bit more challenging to get the data out in the desired format:
$chartData = array();
$chartData[] = array("Day");
foreach($array as $key => $a){
$chartData[0][] = $key;
for($i = 0; $i < count($a); $i++){
if(!is_array($chartData[$i+1])){
$chartData[$i+1] = array();
$chartData[$i+1][] = $a[$i]['day'];
}
$chartData[$i+1][count($chartData[0])-1] = $a[$i]['goals'];
}
}
This should give you the format you need to have the desired chart data table:
[
["Day","team1","team2"]
[1,3,1]
[2,1,2]
[3,0,4]
]
Creating a line for the number of goals (y Axis) for each team over the number of days (x axis). Hope this helps

Related

Arranging array in php

my problem is i can't arrange the array in the structure i want.
array1 and array2 are generated dynamically. as you can see in the array 2 it has a subjectid which is the same in array1, that means, that element is under the subject cpe 305. all elements in the array 2 which has the id of 5 is under the the subject of cpe 305. same logic with cpe 304.
array1:
Array
(
[0] => Array
(
[subjectid] => 5
[subjectcode] => Cpe 305
)
[1] => Array
(
[subjectid] => 4
[subjectcode] => Cpe 304
)
)
array2:
Array
(
[0] => Array
(
[subjectid] => 5
[soid] => 1
[socode] => A
[sodesc] => Ability to apply knowledge of mathematics and science to solve engineering problems
)
[1] => Array
(
[subjectid] => 5
[soid] => 3
[socode] => C
[sodesc] => Ability to design a system, component, or process to meet the desired needs within realistic constraints such as economic, environmental, social, political, ethical, health and safety, manufacturability, and sustainability, in accordance to standards
)
[2] => Array
(
[subjectid] => 5
[soid] => 4
[socode] => D
[sodesc] => Ability to function on multidisciplinary teams
)
[3] => Array
(
[subjectid] => 5
[soid] => 5
[socode] => E
[sodesc] => Ability to identify, formulate, and solve engineering problems
)
[4] => Array
(
[subjectid] => 5
[soid] => 9
[socode] => I
[sodesc] => Recognition of the need for, and an ability to engage in life-long learning
)
[5] => Array
(
[subjectid] => 4
[soid] => 10
[socode] => J
[sodesc] => Knowledge of contemporary issues
)
)
OUTPUT (my desired structure)
Array(
[subjectid] => 5
[subjectcode] => Cpe 305
[sodetails] => array(
[0]=>Array ([soid]=>1
[socode]=>A)
[1]=>Array([soid]=>3
[socode]=>C .....until the last
)
[subjectid] => 4
[subjectcode] => Cpe 305
[sodetails] => array(
[0]=>Array ([soid]=>10
[socode]=>J)
.......until the last
)
what i've tried
this is the code that im testing. i only include few data here in my test code.
$so = array();
$exist = array();
foreach ($this->subject as $key => $value) {
foreach ($this->sodetails as $key2 => $value2) {
if($value['subjectid'] === $value2['subjectid']){
$exist = array(
"subjectid" => $value['subjectid'],
"details" =>array(
"soid" => $value2['soid']
)
);
array_push($so, $exist);
}
}
}
First of all your output array is incorrect. An array cannot have more than one same indexes like "subjectid", "subjectcode". We need to have a different index. It will be wise to use subjectid as index for outer array.
First prepare your outer array as it is array1.
foreach($this->subject as $key => $val){
$myArray[$val['subjectid']]['subjectid'] => $val['subjectid'];
$myArray[$val['subjectid']]['subjectcode'] => $val['subjectcode'];
}
Now iterate your sodetails array.
foreach($this->sodetails as $key => $val){
$temp['soid'] = $val['soid'];
$temp['socode'] = $val['socode'];
array_push($myArray[$val['subjectid']]['sodetails'], $temp);
}
There can be other ways too. But it is my style and I believe it will solve your problem.
You just need to pass subjectid as key in your return array,
$exist = array();
foreach ($this->subject as $key => $value) {
foreach ($this->sodetails as $key2 => $value2) {
if($value['subjectid'] === $value2['subjectid']){
$exist[$value['subjectid']]['subjectid'] = $value['subjectid'];
$exist[$value['subjectid']]['subjectcode'] = $value['subjectcode'];
$exist[$value['subjectid']]['sodetails'] = array(array('soid'=>$value2['soid']),array('socode'=>$value2['socode']));
}
}
}
Instead of running the loop/iterations for m x n times, what you could do is first have the subjectid as the key for the $arrray1 and let the natural PHP array key handling do the job.
$new_array1 = array();
foreach($arrray1 as $item){
$new_array1[$item['subjectcode']] = $item;
}
foreach($array2 as $desc){
if(array_key_exists($desc['subjectid'],$new_array1){
$new_array1[$desc['subjectid']]['desc'][] = $desc;
}
}
This way you only have to make m + n iterations.

find max value of a key in array

I have an array
[DoctorEducation] => Array
(
[0] => Array
(
[id] => 24
[user_id] => 91
[degree_type_id] => 1
[college_hospital] => sms
[diploma_name] =>
[specialization_id] => 0
[start_date] => 02/2009
[end_date] => 03/2012
[year_passing] => 0000
[created] => 2015-10-09 13:14:23
[updated] => 2015-10-09 13:16:18
)
[1] => Array
(
[id] => 26
[user_id] => 91
[degree_type_id] => 5
[college_hospital] => sms
[diploma_name] =>
[specialization_id] => 48
[start_date] => 03/2012
[end_date] => 05/2014
[year_passing] => 0000
[created] => 2015-10-09 13:16:18
[updated] => 2015-10-09 13:16:18
)
)
Now I want to find out which index i.e 0 or 1 or so on have the biggest value of degree_type_id. for example in current array index 1 has the biggest value of degree_type_id i.e 5.
I am getting this from DB. Here is the query
$fields = array(
'User.id',
'User.first_name',
'User.last_name',
'User.gender',
'User.dob',
'User.image',
'Specialization.name',
'User.age'
);
$getSpecialist = $this->User->find('all', array('fields' => $fields), array('conditions' => array('User.role_id' => 3, 'User.status' => 1)));
Try something like this:
$max_index = null;
$max_value = 0;
foreach($DoctorEducation as $key => $array){
if($array['degree_type_id'] > $max_value){
$max_value = $array['degree_type_id'];
$max_index = $key;
}
}
print_r($DoctorEducation[$max_index]);
This gives you the index and the value of the key with the highest degree_type_id
There may be a faster way to do this, but here's my solution:
$to_compare = array();
foreach($DoctorEducation as $idx => $arr){
$to_compare[$idx] = $arr['degree_type_id'];
}
$max = $to_compare[array_search(max($to_compare), $to_compare)];
Pretty simple with several functions:
$key = array_search(max(array_column($array['DoctorEducation'], 'degree_type_id')),
$array['DoctorEducation']);
Extract the appropriate column to an array
Find the maximum value in that column array
Search that column array for the maximum value, which returns the key
If there is more than one occurrence of the maximum value then you will get the first one.

How to return array as multi dimensional array?

I i'm developing php application. I have used Google Chart API for display charts.
I have select and returned necessary data for chart.
I got following array as my output.
print_r($output);
//Out put
Array
(
[0] => Array
(
[month] => April
[sec_id] => 2
[sec_name] => Commerce
[count] => 1
)
[1] => Array
(
[month] => June
[sec_id] => 2
[sec_name] => Commerce
[count] => 3
)
[2] => Array
(
[month] => July
[sec_id] => 2
[sec_name] => Commerce
[count] => 1
)
[3] => Array
(
[month] => August
[sec_id] => 4
[sec_name] => Science
[count] => 3
)
[4] => Array
(
[month] => August
[sec_id] => 3
[sec_name] => Maths
[count] => 2
)
[5] => Array
(
[month] => August
[sec_id] => 1
[sec_name] => Art
[count] => 2
)
[6] => Array
(
[month] => August
[sec_id] => 2
[sec_name] => Commerce
[count] => 2
)
)
print_r(json_encode($output)); // return above array as output
I request above data using ajax ( data type is JSON)
I want to return data as bellow to generate google chart.
[
['Month', 'Art', 'Commerce', 'Maths', 'Sience'],
['April', '', 2, '', ''],
['June', '', 3, '', ''],
['July', '', 1, '', ''],
['August', 2, 2, 3, 3]
]
I tried this this code
$output = array();
$output[0] = array('Month', 'Art', 'Commerce', 'Maths', 'Science');
foreach($records as $key=> $record){
$art =''; $commerce =''; $maths=''; $science='';
if($record['sec_id'] == 1){
$art = $record['count'];
}else if($record['sec_id'] == 2){
$commerce = $record['count'];
}else if($record['sec_id'] == 3){
$maths = $record['count'];
}else if($record['sec_id'] == 4){
$science = $record['count'];
}
$output[++$key] = array(0 => $record['month'], 1 => $art, 2 => $commerce, 3 => $maths, 4 => $science);
}
function super_unique($array){
$result = array_map("unserialize", array_unique(array_map("serialize", $array)));
foreach ($result as $key => $value){
if ( is_array($value)){
$result[$key] = super_unique($value);
}
}
return $result;
}
$output = super_unique($output);
Out put was
[["Month","Art","Commerce","Maths","Science"],["April","","1"],["June","","3"],["July","","1"],{"0":"August","1":"","4":"3"},{"0":"August","1":"","3":"2"},["August","2",""],["August","","2"]]
This is pretty straightforward to loop through and reorganize, particularly since your sec_ids match up nicely with the array indices.
Example:
$temp = array();
$output = array(
array('Month', 'Art', 'Commerce', 'Maths', 'Science')
);
foreach ($records as $record) {
$month = $record["month"];
$sec_id = $record["sec_id"];
$count = $record["count"];
if (!isset($temp[$month])) {
$temp[$month] = array_fill(0, 5, '');
}
$temp[$month][0] = $month;
$temp[$month][$sec_id] += $count;
}
$output = array_merge($output, array_values($temp));
echo json_encode($output);
Output:
[["Month","Art","Commerce","Maths","Science"],["April","",2,"",""],["June","",3,"",""],["July","",1,"",""],["August",2,2,2,3]]
Let's rethink your algorithm. As you go through each element in records, we need to ask two things: what data are we pulling out and what do we want to do with it?
The first question is simple: we're just pulling out the value 'count'.
The second question is going to determine our algorithm. What we want to do is take that 'count' value, and stick it a particular spot in our ourpur array.
Looking at the output array as a table, we can see that the desired position of 'count' is determined by the 'month' field (which determines the row) and by the 'sec_id'/'sec_name' fields (which determine the column). So what you want your loop to look like is this...
foreach($records as $record)
{
$output[$record['month']][$record['sec_id']] = $record['count']
}
The first caveat to this is that for each unique month, you do still need to create and initialize the sub-array, and you must do it only once. So, the loop becomes.
foreach($records as $record)
{
if(!is_array($output[$record['month']]))
$output[$record['month']] = array(0 => $record['month'], 1 => '', 2 => '', 3 => '', 4 => '');
$output[$record['month']][$record['sec_id']] = $record['count']
}
Finally, we used the actual month name as the keys in the top-level array. To comply with the numeric-only keys specified in your desired output, we can ditch those keys with the following piece of code.
$output = array_values($output)
If I'm right in thinking you were trying to use super_unique() to combine rows with the same month, that's not what it was doing at all. Firstly, array_unique() doesn't combine rows, it eliminates duplicates. Since you were comparing serialized rows, rather than just looking at the month field, none of your rows were duplicates, so that function was doing nothing. Furthermore, since several of your array fields were set to '', the serialize/unserialize process was actually causing those fields to get dropped, which is why you were ending up with sub-arrays of less than five elements, and with associative keys.

Parsing array values into multidimensional array

I have some data I retrieve from a JSON feed that currently is being parsed into an array like this: (simplifying for demonstration purposes)
So pretty much an array returns a movie theater name, with the showtimes associated with that particular theater.
[0] => American Theater
[1] => 2014-06-04T13:10
[2] => 2014-06-04T15:10
[3] => Grand Theater
[4] => 2014-06-04T15:30
[5] => 2014-06-04T19:10
How would I parse this array to be multidimensional, for instance:
Array
(
[0] => Array
(
[theater] => Array
(
[name] => American Theater
)
[showtimes] => Array
(
[1] => 2014-06-04T13:10
[2] => 2014-06-04T15:10
)
)
[1] => Array
(
[theater] => Array
(
[name] => Grand Theater
)
[showtimes] => Array
(
[1] => 2014-06-04T15:30
[2] => 2014-06-04T19:10
)
)
)
I'm assuming you're trying to access some api and have no control over how the data is passed back to you? If you do then the API should be responsible for returning a sensible schema.
But if you're forced to work with this array and the amount of showtimes are unknown to you, then you can do something like this:
$array = array(
'American Theater',
'2014-06-04T13:10',
'2014-06-04T15:10',
'Grand Theater',
'2014-06-04T15:30',
'2014-06-04T19:10'
);
$i = 0;
foreach ($array as $key => $value) {
if (strtotime($value)) {
$theaters[$i - 1]['showtimes'][] = $value;
}
else {
$theaters[$i]['theater']['name'] = $value;
$i++;
}
}
Outcome
To walk you through it, $array is whatever the returned dataset is. We set an index in the $i value and want to only increment it if we determine we've detected a theater name. Within the loop we first try to determine if the string can be converted to a php time value. If it cannot we add the theater name to our new schema structure, and increment our index value. Since times are always added to theater names, we are expecting the first index number to always be one higher than what we want to add the showtime to.
This will fail to be accurate in cases when a theater name is convertible to a time value in such cases like Next Month. There are a couple of other ways to solve this with regex or by inspecting the string for certain characters and their position since the time format will remain the same.
You could replace the strtotime() with:
$str = str_split($value);
if (($str[4] && $str[7]) == '-' && $str[10] == 'T' && $str[13] == ':' ) {
$theaters[$i - 1]['showtimes'][] = $value;
}
If you want such structure, you need to create a new copy of it. You may also need to chunk/group them by three's using array_chunk first, and then, from there, you can loop it now and start creating the desired format.
Consider this example:
$old_values = array('American Theater', '2014-06-04T13:10', '2014-06-04T15:10', 'Grand Theater', '2014-06-04T15:30', '2014-06-04T19:10');
$old_values = array_chunk($old_values, 3);
$new_values = array();
foreach($old_values as $key => $value) {
$new_values[] = array(
'theater' => array('name' => $value[0]),
'showtimes' => array(1 => $value[1], 2 => $value[2]),
);
}
Edit: As mentioned, one theater can have many showtimes, therefore this current solution will fail. This may be an alternative (you may need to check each element if its a theater name or a date). Consider this example:
$old_values = array(
'American Theater',
'2014-06-04T13:10',
'2014-06-04T15:10',
'Grand Theater',
'2014-06-04T15:30',
'2014-06-04T19:10',
'Magic Johnson Theater',
'2014-06-04T19:10',
'2014-06-04T19:10',
'2014-06-04T19:10',
'Mall of America Theater',
'2014-06-04T19:10',
'2014-06-04T19:10',
'2014-06-04T19:10',
'2014-06-04T19:10',
);
$new_values = array();
$current_key = 0;
foreach($old_values as $key => $value) {
$current_value = $value;
$pieces = explode('T', $current_value);
$dates = explode('-', $pieces[0]);
if(count($dates) == 3) {
$new_values[$current_key]['showtimes'][] = $current_value;
} else {
$current_key++;
$new_values[$current_key]['theater']['name'] = $current_value;
}
}
Sample Output:
Array
(
[1] => Array
(
[theater] => Array
(
[name] => American Theater
)
[showtimes] => Array
(
[0] => 2014-06-04T13:10
[1] => 2014-06-04T15:10
)
)
[2] => Array
(
[theater] => Array
(
[name] => Grand Theater
)
[showtimes] => Array
(
[0] => 2014-06-04T15:30
[1] => 2014-06-04T19:10
)
)
[3] => Array
(
[theater] => Array
(
[name] => Magic Johnson Theater
)
[showtimes] => Array
(
[0] => 2014-06-04T19:10
[1] => 2014-06-04T19:10
[2] => 2014-06-04T19:10
)
)
[4] => Array
(
[theater] => Array
(
[name] => Mall of America Theater
)
[showtimes] => Array
(
[0] => 2014-06-04T19:10
[1] => 2014-06-04T19:10
[2] => 2014-06-04T19:10
[3] => 2014-06-04T19:10
)
)
)
Sample Fiddle

Counting unique arrays inside the array in PHP?

I have some array containing other arrays:
Array
(
[0] => Slip Object
(
[userId:protected] => 1
[parentSlipId:protected] => 0
[id:protected] => 25
[madeDatetime:protected] => 2011-04-19 17:13:09
[stake:protected] => 34.00
[status:protected] => 6
)
[1] => Slip Object
(
[userId:protected] => 1
[parentSlipId:protected] => 0
[id:protected] => 25
[madeDatetime:protected] => 2011-04-19 17:13:09
[stake:protected] => 34.00
[status:protected] => 6
)
[2] => Slip Object
(
[userId:protected] => 1
[parentSlipId:protected] => 0
[id:protected] => 24
[madeDatetime:protected] => 2011-04-18 11:31:26
[stake:protected] => 13.00
[status:protected] => 6
)
)
What's the best way of counting unique arrays?
Off the top of my head you could try:
$hashes = array();
$uniques = 0;
foreach($array as $slip) {
$hash = sha1(serialize($slip));
if(!in_array($hash, $hashes)) {
++$uniques;
$hashes[] = $hash;
}
}
var_dump($uniques); // prints total number of unique objects.
Edit:
#biakaveron's idea looks better though and could be adapted to:
$uniques = count(array_unique($array, SORT_REGULAR));
var_dump($uniques); // prints total number of unique objects.
This previous question has various solutions for removing duplicate arrays from within an array. If you implement any of them and then use sizeof() on the returned array you will have your solution.
eg:
<?php
$yourarray = array();
$tmp = array ();
foreach ($yourarray as $row)
if (!in_array($row,$tmp)) array_push($tmp,$row);
echo sizeof($tmp);
?>

Categories