Multi Array Prep for Charting - php
I searched for answers and could not find one. This is long and complex and looking for someone smart than me to answer.
Here is the situation. Using PHP, SQL, and trying Pchart.
1) Please do not suggest other charting tools. That is a waste of your time and mine. Other charting tool offer JAVA, JAVASCRIPT, JQUERY, and more. They are slick but what I need is simple (server side creation of data created dynamically and rendered using something on server. Why put the load on client side - at least for now while I investigate.
2) This is PHP specific question not the pchart tool.
Here is the scenario.
I have a table with results from swimming.
I can get the data formatted the way I need.
See below prints.
Array (assume this is first array)
(
[0] => Freestyle 50
[1] => Freestyle 100
[2] => Backstroke 50
[3] => Butterfly 50
[4] => Medley 100
)
Array (assume this is second array)
(
[Backstroke 50] => Array
(
[2012-11-04] => 51.08
[2012-11-10] => 52.50
[2012-11-25] => 55.48
[2012-12-01] => 47.56
[2012-12-08] => 44.51
[2012-12-15] => 49.46
[2013-01-19] => 47.12
[2013-11-03] => 42.52
[2013-11-09] => 40.94
[2013-11-10] => 42.97
[2013-11-16] => 41.36
[2013-12-01] => 45.16
[2013-12-08] => 40.59
[2014-01-12] => 37.67
[2014-02-01] => 37.70
)
[Freestyle 50] => Array
(
[2012-11-04] => 45.33
[2012-11-25] => 50.12
[2013-11-03] => 37.01
[2013-11-10] => 36.73
[2013-12-01] => 39.94
[2014-01-04] => 39.77
[2014-01-12] => 34.22
[2014-02-01] => 34.93
)
[Freestyle 100] => Array
(
[2012-11-04] => 137.73
[2012-11-10] => 126.86
[2012-12-08] => 133.65
[2013-11-03] => 124.14
[2013-11-10] => 121.94
[2013-11-16] => 121.10
[2013-12-01] => 130.99
[2013-12-07] => 118.27
[2013-12-08] => 122.44
[2014-01-04] => 131.38
[2014-01-11] => 115.95
[2014-01-18] => 120.06
)
[Medley 100] => Array
(
[2012-12-01] => 146.66
[2013-01-19] => 143.88
[2013-11-03] => 137.37
[2013-11-09] => 133.05
[2013-11-10] => 134.69
[2013-12-01] => 145.29
[2013-12-07] => 130.15
[2013-12-08] => 130.92
[2014-01-12] => 129.33
[2014-01-18] => 130.81
[2014-02-01] => 128.57
)
[Butterfly 50] => Array
(
[2013-12-08] => 46.82
[2014-01-12] => 43.66
)
)
Array (assume this is third array)
(
[2] => 2012-11-04
[14] => 2012-11-10
[1] => 2012-11-25
[31] => 2012-12-01
[15] => 2012-12-08
[26] => 2012-12-15
[24] => 2013-01-19
[7] => 2013-11-03
[28] => 2013-11-09
[4] => 2013-11-10
[11] => 2013-11-16
[3] => 2013-12-01
[9] => 2013-12-07
[12] => 2013-12-08
[5] => 2014-01-04
[10] => 2014-01-11
[0] => 2014-01-12
[13] => 2014-01-18
[6] => 2014-02-01
)
To line up the charting tool I need to have it in a string like this.
============== Backstroke 50 =================
51.08,52.50,55.48,47.56,44.51,49.46,47.12,42.52,40.94,42.97,41.36,45.16,40.59,37.67,37.70Create or Render Chart
"2012-11-04","2012-11-10","2012-11-25","2012-12-01","2012-12-08","2012-12-15","2013-01-19","2013-11-03","2013-11-09","2013-11-10","2013-11-16","2013-12-01","2013-12-08","2014-01-12","2014-02-01"
============== Freestyle 50 =================
45.33,50.12,37.01,36.73,39.94,39.77,34.22,34.93
"2012-11-04","2012-11-25","2013-11-03","2013-11-10","2013-12-01","2014-01-04","2014-01-12","2014-02-01"
============== Freestyle 100 =================
137.73,126.86,133.65,124.14,121.94,121.10,130.99,118.27,122.44,131.38,115.95,120.06
"2012-11-04","2012-11-10","2012-12-08","2013-11-03","2013-11-10","2013-11-16","2013-12-01","2013-12-07","2013-12-08","2014-01-04","2014-01-11","2014-01-18"
============== Medley 100 =================
146.66,143.88,137.37,133.05,134.69,145.29,130.15,130.92,129.33,130.81,128.57
"2012-12-01","2013-01-19","2013-11-03","2013-11-09","2013-11-10","2013-12-01","2013-12-07","2013-12-08","2014-01-12","2014-01-18","2014-02-01"
============== Butterfly 50 =================
46.82,43.66
"2013-12-08","2014-01-12"
What I am trying to achieve is to get the array #3 assumed. To be inserted in all of these list above. Example: butterfly has two dates. But I want to show all dates, and insert void times for the dates. This will allow the line getting rendered on the chart to be full use of the dates being displayed.
Here is the code:
First Array: Plus third array below this while:
while($result->fetchInto($data,DB_FETCHMODE_ASSOC)) {
$count ++;
$stroke = $data['stroke'];
$distance = $data['distance'];
$start = mysql2date($data['start']);
$dateARR[] = $data['start'];
$stroke = trim($c->getStrokeName($stroke));
$strokestr = $stroke . " " . $distance;
if($strokestr != $lastEvent) {
$strokeARR[] = $strokestr;
$lastEvent = $strokestr;
}
$lastEvent = $strokestr;
}
$dateARR = array_unique($dateARR);
asort($dateARR);
Second Array:
while($result->fetchInto($data,DB_FETCHMODE_ASSOC)) {
$stroke = $data['stroke'];
$distance = $data['distance'];
$start = mysql2date($data['start']);
$time = $c->integer2time($data['time']);
$time = str_replace(':', '', $time);
$meet = $data['meet'];
$stroke = trim($c->getStrokeName($stroke));
$strokestr = $stroke . " " . $distance;
$timeARR[$strokestr][$data['start']] = $time;
$count ++;
}
Should or how to make use of the while loop two in the second array and insert missing dates. Should I prefill the dates then compare during the loop to place the time or the VOID of time while building timeARR?
Any ideas out there?
Figured it out now.
// Loop through Stroke and add all dates.
foreach ($strokeARR as $key1 => $val1) {
print "$key1 = $val1\n";
foreach ($dateARR as $key2 => $val2) {
print "$key2 = $val2\n";
$TestARR[$val1][$val2] = "VOID";
}
}
I had to loop through and prefill with full date range then pre fill with VOID.
When I enter the second while loop I end up inserting time where needed. worked out. I wish I can do this in one pass but I am not that good.
Related
Create PHP Array Where Matching Keys have Some Value
This is the first post from a PHP noob. My question relates to an HTML/PHP form which posts the following three types of data generated by a MySQL query: ID (always posted via a hidden input field) Mileage (only some entries may be completed, others might be left blank) Vehicle Type (always posted via a hidden input field) This data is all for one of three companies that are selected on the page preceding the data-posting page ie. Step One: Choose company and year. Press submit. Step Two: See results from MySQL query and enter in mileages where necessary. Press submit. Step Three: (that's why I'm here) I've stuffed this data into what I (probably mistakenly) believe is a multidimensional array called $idmilearray by using the following code: if(isset($_POST['mileage'])) { $mileagenumber = $_POST['mileage']; } if(isset($_POST['idnos'])) { $idnumber = $_POST['idnos']; } if(isset($_POST['vehicle'])) { $vehicletype = $_POST['vehicle']; } $idmilearray = array( 'ids' => $idnumber, 'mileage' => $mileagenumber, 'vtype' => $vehicletype ); foreach($idmilearray as $inputs) { $inputs = $idmilearray['ids']; $inputs = $idmilearray['mileage']; $inputs = $idmilearray['vtype']; } If I execute a print_r on the $idmilearray I get the following results: Array ( [ids] => Array ( [0] => 35 [1] => 22 [2] => 32 [3] => 38 [4] => 36 [5] => 39 [6] => 16 [7] => 20 [8] => 48 [9] => 46 ) [mileage] => Array ( [0] => 334 [1] => 56 [2] => [3] => 43 [4] => [5] => [6] => [7] => [8] => 11 [9] => 5 ) [vtype] => Array ( [0] => 10T [1] => 10T [2] => 10T [3] => Artic [4] => 10T [5] => Artic [6] => Artic [7] => 10T [8] => Artic [9] => 10T ) What I would like to do is to create another array (the values of which I can use in later SQL queries) but only where the keys contain something in [ids][0], [mileage][0] and [vtype][0] and so on and so forth. I'd like to use [mileage] as the 'reference array'. I've been playing around with array_intersect_key and array_diff_key but I've hit a big and rather a nasty wall. Can anyone help or give some pointers? Thanks very much for your time. Regards, External.
You can use what you have to insert directly into mysql as follows: foreach ( $idmilearray['mileage'] as $KEY => $VAL ) { if ( empty($VAL) ) continue; $query = "INSERT INTO `tableName` (id, mileage, vtype) VALUES ('{$idmilearray['ids'][$KEY]}', '$VAL', '{$idmilearray['vtype'][$KEY]}')"; } Or if you really want to merge everything for further processing or whatever reason you can do it like so: $NewArray = []; foreach ( $idmilearray['mileage'] as $KEY => $VAL ) { if ( empty($VAL) ) continue; $NewArray[] = array('id' => $idmilearray['ids'][$KEY], 'mileage' => $VAL, 'vtype' => $idmilearray['vtype'][$KEY]); } Ofcourse there are many other possible ways to do this, but these are the easiest given what you currently have.
Just add another foreach, inside your existing foreach and fill your new array by checking the old array values with if (!empty($old_array)) {} Example: foreach($idmilearray as $inputs) { $inputs = $idmilearray['ids']; $inputs = $idmilearray['mileage']; // This is the one you want, right? $inputs = $idmilearray['vtype']; } To do the job you need, it would be something like this: $new_array = []; // Short array syntax (PHP 5.3+) foreach($idmilearray as $inputs) { $inputs = $idmilearray['ids']; foreach($idmilearray['mileage'] as $mileage) { if (!empty($mileage)) { $new_array[] = $mileage; } } $inputs = $idmilearray['vtype']; } Now you have new array ($new_array) filled only with the keys that links to existing values. I hope it helps you.
Explode foreach to new array
I have JSON API response which look something like this Array ( [sections] => Array ( [0] => Array ( [id] => 115000089967 [url] => xxxxx [html_url] => ArticleHTML1 [category_id] => 204458828 [position] => 0 [sorting] => manual [created_at] => 2016-12-19T14:56:23Z [updated_at] => 2017-02-03T08:23:04Z [name] => ArticleName1 [description] => [outdated] => ) [1] => Array ( [id] => 207077828 [url] => xxxxxx [html_url] => ArticleHTML2 [category_id] => 204458828 [position] => 1 [sorting] => manual [created_at] => 2016-11-14T09:28:30Z [updated_at] => 2017-02-02T09:15:42Z [name] => ArticleName2 [description] => [outdated] => ) ) [page] => 1 [per_page] => 30 [page_count] => 1 [sort_by] => position [sort_order] => asc ) I have successfully iterated this with foreach, so return looks like this: ArticleName1 ArticleHTML1 ArticleName2 ArticleHTML2 So I took [name] and [html_url] from each like this: $details1 = array('name'); $details2 = array('html_url'); foreach($sections['sections'] as $article) { foreach($details1 as $detail) { echo "$article[$detail] "; } foreach($details2 as $detail) { echo "$article[$detail]\n"; } } But what I want next is that, that response should be exploded to one single array like this: Array ( [0] => ArticleName1 ArticleHTML1 [1] => ArticleName2 ArticleHTML2 ) I already managed to explode those to individual arrays: foreach($sections['sections'] as $article) { foreach($details1 as $detail) { $name = "$article[$detail] "; } foreach($details2 as $detail) { $url = "$article[$detail]\n"; } $string = $name . $url; $array = explode(' ', $string, 1); print_r($array); } but I need just one array. How? I'm lost or just doesn't understand, am I even close? EDIT The thing here is that the JSON dump is pretty large and I only need few things (name and url). So I was thinking that I first grab the whole thing, then I just take the names and urls (like the first foreach is doing), and then put those back to array. Because from those names and urls I need only last 12 keys, and taking those from sinlge array would be easy. Tho it would be perfect, if I could sort out the keys which I don't want, in the first place. That would solve my problem. Then I wouldn't need a new array etc.
You're making this much more difficult than it needs to be. It's just a single loop: $array = array(); foreach ($sections['sections'] as $article) { $array[] = $article['name'] . ' ' . $article['html_url']; }
Updating database with foreach is changing the array before updating
I have an array with names, goal differences and so on for football teams that I want to put in a table, but during the foreach the last key in the array is changed somehow. Last two keys before foreach [18] => Array ( [team_code] => 4 [team_name] => Newcastle [points] => 6 [goals_for] => 12 [goals_against] => 22 [goal_difference] => -10 ) [19] => Array ( [team_code] => 7 [team_name] => Aston Villa [points] => 4 [goals_for] => 9 [goals_against] => 17 [goal_difference] => -8 ) ) After foreach [18] => Array ( [team_code] => 4 [team_name] => Newcastle [points] => 6 [goals_for] => 12 [goals_against] => 22 [goal_difference] => -10 ) [19] => Array ( [team_code] => 4 [team_name] => Newcastle [points] => 6 [goals_for] => 12 [goals_against] => 22 [goal_difference] => -10 ) ) My foreach looks like this foreach ($teams as $team) { $team_code = $team['team_code']; $team_name = $team['team_name']; $points = $team['points']; $goals_for = $team['goals_for']; $goals_against = $team['goals_against']; $goal_difference = $team['goal_difference']; if ($update_query = $conn->query("UPDATE teams SET points = $points, goals_for = $goals_for, goals_against = $goals_against, goal_difference = $goal_difference WHERE team_code = $team_code")) { echo 'Updated '.$team_name.'<br>'; } else { $update_query->error; } } Why is the last key changed? It happens before the query is run, because the row doesn't get updated. All the others update as they should.
Thanks to VolkerK I managed to solve it. I have another foreach with a reference to &$team before the foreach, and putting unset($team) between the two foreachs solved the problem.
I don't think that there's anything wrong with your php script. I would take a look at how the array is build before it get to the foreach loop. How is the form for which you enter the data set up. If you are entering multiple teams at once, how are you differentiating the elements
How to read file having extension .asc in php and it should create array with .mark contained by numeric value?
1. 00:00:00:00 00:00:00:01 Hi 2. 00:00:37:15 00:00:38:16 Hiiii How Are you? 3. 00:00:40:01 00:00:41:19 Fine. I tried to read above file but I didn't get required result. I need result in: array( [0] => Array ( [asc_id] => 1. [start_time] => 00:00:00:00 [end_time] => 00:00:00:01 [action_1] => Hi [action_2] => ) [1] => Array ( [asc_id] => 2. [start_time] => 00:00:37:15 [end_time] => 00:00:38:16 [action_1] => Hiiii [action_2] => How Are you? ) [2] => Array ( [asc_id] => 3. [start_time] => 00:00:53:02 [end_time] => 00:00:53:20 [action_1] => Fine. [action_2] => ) )
Here's a simple start, that assumes your input will always be formatted the same as above. There are many improvements you could make to this for error checking and better flexibility on the format of the input. $myarray = array(); $file = file('file.asc'); while ($line = array_shift($file)) { if (preg_match('/\d+\.$/', $line)) { $myarray[] = array( 'asc_id' => trim($line), 'start_time' => trim(array_shift($file)), 'end_time' => trim(array_shift($file)), 'action_1' => trim(array_shift($file)), 'action_2' => trim(array_shift($file)), ); } } print_r($myarray);
This is 'file processing' requirement. Which are: read a 'group' of records, 5 in this case convert them into an associated array append them to a PHP array. Approach: Process the records in groups specified size Provide a 'place' for processing the start of the 'group' Provide a place for processing the end of the group As these are 'nested' groups I use a 'read ahead' technique. Complete code at pastebin.com 'long-winded'? maybe :) The code: Data definitions: /** * Data definition */ define('SOURCE_FILE', __DIR__ . '/Q31609517-data.asc'); define('MAX_LINE_LEN', 128); // data group details define ('DATA_GROUP_SIZE', 5); // allow easy changing of data names and changing the input order $itemNames = array('asc_id', 'start_time', 'end_time', 'action_1', 'action_2'); Process the data: /** * Process the file */ $sourceFile = fopen(SOURCE_FILE, 'r'); $currentLine = fgets($sourceFile, MAX_LINE_LEN); // always use 'read ahead'; // process the file while (!feof($sourceFile) && $currentLine !== false) { // start group processing $currentGroupLine = 0; $currentGroup = array(); while ($currentGroupLine < DATA_GROUP_SIZE) { $currentGroup[$itemNames[$currentGroupLine]] = trim($currentLine); $currentGroupLine++; $currentLine = fgets($sourceFile, MAX_LINE_LEN); // always use 'read ahead'; } // process complete group $outData[] = $currentGroup; } fclose($sourceFile); The test data (5 lines per group): 1. 00:00:00:00 00:00:00:01 Hi 2. 00:00:37:15 00:00:38:16 Hiiii How Are you? 3. 00:00:40:01 00:00:41:19 Fine. The output: Array ( [0] => Array ( [asc_id] => 1. [start_time] => 00:00:00:00 [end_time] => 00:00:00:01 [action_1] => Hi [action_2] => ) [1] => Array ( [asc_id] => 2. [start_time] => 00:00:37:15 [end_time] => 00:00:38:16 [action_1] => Hiiii [action_2] => How Are you? ) [2] => Array ( [asc_id] => 3. [start_time] => 00:00:40:01 [end_time] => 00:00:41:19 [action_1] => Fine. [action_2] => ) )
Formatting an array to order by specified unix timestamp in PHP
I have an array which has a timestamp consistently on [3] ( an example of the array data below) I would like the array to be sorted using the timestamp. I've seen a few stackoverflow posts that apparently do this using two methods, array_multisort() and usort() but I've been unable to replicate either. Here is what I've tried based on my own code: Attempt 1 - I pass the array to usort, then attempt to take it apart with the foreach. Applying this method definitely changes the order of the results, but the dates seems to be no specific order (ascending, descending). function sortArray($a1, $a2){ if ($a1[3] == $a2[3]) return 0; return ($a1[3] > $a2[3]) ? -1 : 1; } usort($the_array, "sortArray"); foreach($the_array as $sh) { $uid = $sh['uid']; $username = $sh['username']; $datetime = $sh['datetime']; $type = $sh['type']; echo "<p> $uid , $username, $datetime, $type </p>"; } Attempt 2 - tried using array_multisor() which again gives me results in a different order but I don't understand what it is sorting by exactly. foreach ($the_array as $key => $node) { $timestamps[$key] = $node[3]; } array_multisort($timestamps, SORT_ASC, $the_array); //process the array with a foreach to show results My theory here is that it isn't properly processing the unix timestamp and I'm not sure what I can do about that. Is it smart to take out all the characters of the timestamp so it is a simple line of numbers ( 2014-01-02 03:02:12 becomes 20140102030212 )? Or is there another way to process it with the timestamp in it's current form? Here is an example of the data in the array: Array ( [0] => Array ( [uid] => 20013 [0] => 20013 [username] => myhipswontlie [1] => myhipswontlie [rating] => 4.00 [2] => 4.00 [datetime] => 2014-01-27 23:40:56 [3] => 2014-01-27 23:40:56 [type] => rated [4] => rated ) [1] => Array ( [uid] => 20025 [0] => 20025 [username] => brasilchika [1] => brasilchika [rating] => 4.00 [2] => 4.00 [datetime] => 2014-01-02 03:02:12 [3] => 2014-01-02 03:02:12 [type] => rated [4] => rated ) [2] => Array ( [uid] => 10002 [0] => 10002 [username] => crtten [1] => crtten [datetime] => 2014-01-25 01:33:34 [2] => 2014-01-25 01:33:34 [type] => visits [3] => visits ) )
Your issue is your numeric keys don't seem to match up in your arrays. Sometimes the datetime is found in the 3rd key, sometime it is found in the second key (which is odd considering they look like they come from mysql_fetch_array() which will make uniform arrays). To solve this you should use the associative array key instead: function sortArray($a1, $a2){ if ($a1['datetime'] == $a2['datetime']) return 0; return ($a1['datetime'] > $a2['datetime']) ? -1 : 1; } usort($the_array, "sortArray");