xenomorf Posted July 12, 2017 Share Posted July 12, 2017 hi all, i want to create a table from an array based on a key value, but my problem is, not all data in my array has the same array key with same value. i have asked this same problem on StackOverflow StackOverflow Link the last answer is doing what i need but it only find the first data. subsequent data is just ignored. this is my initial code, which is working but not ignoring missing data foreach($graph as $grade => $data ) { echo '<strong>'.strtoupper($grade).'</strong></br>'; echo 'Data Count: <b>'.count($data).'</b>'; //start the table for each grade echo '<table border=1>'; echo '<thead>'; echo '<tr>'; echo '<th>Monitor Label</th>'; for($i=0;$i < count($data['age']);$i++) { echo '<th>'.$data['age'][$i].'D</th>'; } echo '</tr>'; echo '</thead>'; echo '<tbody>'; for ($i=0;$i < count($data)-1; $i++) { echo '<tr>'; echo '<td>'.$data[$i]['label'].'</td>'; foreach($data[$i]['data'] as $x) { echo '<td>'.$x['y'].'</td>'; } echo '</tr>'; } echo '</tbody>'; echo '</table>'; } my initial code produce this table +---------------+----------+-----------+-----------+-----------+-----------+-----+-----+ | Monitor Label | 1D | 2D | 3D | 6D | 7D | 15D | 28D | +---------------+----------+-----------+-----------+-----------+-----------+-----+-----+ | C81 | 6.220000 | 10.220000 | 21.440000 | 30.780000 | | | | | C82 | 8.000000 | 20.890000 | 30.670000 | 32.555000 | 51.110000 | | | | C83 | 7.110000 | 19.780000 | 23.560000 | 32.225000 | 38.890000 | | | +---------------+----------+-----------+-----------+-----------+-----------+-----+-----+ this is the answer from SO which is working, but only on the first data it found. the rest is just ignored foreach($graph as $grade => $data ) { echo '<strong>'.strtoupper($grade).'</strong></br>'; //start the table for each grade echo '<table border=1>'; echo '<thead>'; echo '<tr>'; echo '<th>Monitor Label</th>'; for($i=0;$i < count($data['age']);$i++) { echo '<th>'.$data['age'][$i].'D</th>'; } echo '</tr>'; echo '</thead>'; echo '<tbody>'; for ($i=0;$i < count($data)-1; $i++) { echo '<tr>'; echo '<td>'.$data[$i]['label'].'</td>'; for ($y=0; $y < count($data['age']); $y++) { if ( isset($data[$i]['data'][$y]) ) { if ( $data[$i]['data'][$y]['x'] == $data['age'][$i] ) { echo '<td>'.$data[$i]['data'][$y]['y'].'</td>'; } else { echo '<td>-</td>'; } } else { echo '<td>-</td>'; } } echo '</tr>'; } echo '</tbody>'; echo '</table>'; } above code produce this table +---------------+----------+-----------+----+----+----+-----+-----+ | Monitor Label | 1D | 2D | 3D | 6D | 7D | 15D | 28D | +---------------+----------+-----------+----+----+----+-----+-----+ | C81 | 6.220000 | - | - | - | - | - | - | | C82 | - | - | - | - | - | - | - | | C83 | - | 19.780000 | - | - | - | - | - | +---------------+----------+-----------+----+----+----+-----+-----+ my serialized data is as follows a:1:{s:3:"25p";a:4:{i:0;a:4:{s:2:"id";i:353;s:5:"label";s:3:"C81";s:7:"casting";s:11:"21 Mar 2017";s:4:"data";a:4:{i:0;a:2:{s:1:"x";i:1;s:1:"y";s:8:"6.220000";}i:1;a:2:{s:1:"x";i:2;s:1:"y";s:9:"10.220000";}i:2;a:2:{s:1:"x";i:7;s:1:"y";s:9:"21.440000";}i:3;a:2:{s:1:"x";i:28;s:1:"y";s:9:"30.780000";}}}i:1;a:4:{s:2:"id";i:354;s:5:"label";s:3:"C82";s:7:"casting";s:11:"21 Mar 2017";s:4:"data";a:5:{i:0;a:2:{s:1:"x";i:1;s:1:"y";s:8:"8.000000";}i:1;a:2:{s:1:"x";i:3;s:1:"y";s:9:"20.890000";}i:2;a:2:{s:1:"x";i:6;s:1:"y";s:9:"30.670000";}i:3;a:2:{s:1:"x";i:7;s:1:"y";s:9:"32.555000";}i:4;a:2:{s:1:"x";i:28;s:1:"y";s:9:"51.110000";}}}i:2;a:4:{s:2:"id";i:355;s:5:"label";s:3:"C83";s:7:"casting";s:11:"21 Mar 2017";s:4:"data";a:5:{i:0;a:2:{s:1:"x";i:1;s:1:"y";s:8:"7.110000";}i:1;a:2:{s:1:"x";i:3;s:1:"y";s:9:"19.780000";}i:2;a:2:{s:1:"x";i:6;s:1:"y";s:9:"23.560000";}i:3;a:2:{s:1:"x";i:7;s:1:"y";s:9:"32.225000";}i:4;a:2:{s:1:"x";i:15;s:1:"y";s:9:"38.890000";}}}s:3:"age";a:7:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:6;i:4;i:7;i:5;i:15;i:6;i:28;}}} the 'age' key is created based on the flatten and unique value of 'data[x]' please help me doing this table. i am stuck on this problem for 2 days now. :help: :help: or if there is any alternative way which i can display the data? Quote Link to comment Share on other sites More sharing options...
Solution requinix Posted July 12, 2017 Solution Share Posted July 12, 2017 This goes so much more easily when you preprocess the data into associative arrays. $graph is the unserialized array you posted* but without the [age] you added to it. <?php foreach ($graph as $grade => $data) { $monitors = $days = []; // preprocess foreach ($data as $data2) { $monitors[$data2["label"]] = []; foreach ($data2["data"] as $data3) { $days[] = $data3["x"]; $monitors[$data2["label"]][$data3["x"]] = $data3["y"]; } } // clean $days = array_unique($days); sort($days, SORT_NUMERIC); // draw table ?> <strong><?=strtoupper($grade)?></strong><br> <table border="1"> <thead> <tr> <th>Monitor Label</th> <?php foreach ($days as $d) { ?> <th><?=$d?>D</th> <?php } ?> </tr> </thead> <tbody> <?php foreach ($monitors as $label => $mdata) { ?> <tr> <td><?=$label?></td> <?php foreach ($days as $d) { ?> <td><?=$mdata[$d] ?? ""?></td> <?php } ?> </tr> <?php } ?> </tbody> </table> <?php } <strong>25P</strong><br> <table border="1"> <thead> <tr> <th>Monitor Label</th> <th>1D</th> <th>2D</th> <th>3D</th> <th>6D</th> <th>7D</th> <th>15D</th> <th>28D</th> </tr> </thead> <tbody> <tr> <td>C81</td> <td>6.220000</td> <td>10.220000</td> <td></td> <td></td> <td>21.440000</td> <td></td> <td>30.780000</td> </tr> <tr> <td>C82</td> <td>8.000000</td> <td></td> <td>20.890000</td> <td>30.670000</td> <td>32.555000</td> <td></td> <td>51.110000</td> </tr> <tr> <td>C83</td> <td>7.110000</td> <td></td> <td>19.780000</td> <td>23.560000</td> <td>32.225000</td> <td>38.890000</td> <td></td> </tr> </tbody> </table>* Please don't post serialized data. It's impossible for humans to read. Post the print_r or var_dump output. Quote Link to comment Share on other sites More sharing options...
xenomorf Posted July 13, 2017 Author Share Posted July 13, 2017 thank you for the reply and sorry, i thought it will be easier to use the data directly if i post it in serialized form. if the data is preprocess before echoing the table, i can remove the [age] data right? the data is actually pulled from database joining several table and glue it together in that array format. I then added the [age] data later before creating the table. Quote Link to comment Share on other sites More sharing options...
requinix Posted July 13, 2017 Share Posted July 13, 2017 if the data is preprocess before echoing the table, i can remove the [age] data right?Yes. In fact you need to remove it... is what I would say, except the data is actually pulled from database joining several table and glue it together in that array format.What's the structure of that data? Quote Link to comment Share on other sites More sharing options...
xenomorf Posted July 13, 2017 Author Share Posted July 13, 2017 your answer works perfect for my need but slight problem echo '<td>'.$mdata[$d] ?? 'N/A'.'</td>'; this should be the same as echo isset($mdata[$d]) ? '<td>'.$mdata[$d].'</td>' : '<td> N/A </td>'; but the first code will not show N/A but the second do show N/A Array ( [clientId] => 23 [clientName] => EG [sizeId] => 1 [sample] => 6 [monitorId] => 353 [monitor_label] => C81 [remark] => Trial mix [slump] => 115 [casting_date] => 2017-03-21 [casting_time] => 00:17:15 [grade] => 25 [mix_design] => p [p_title] => SA [p_alias] => SA [techId] => 2 [tech_name] => HF [c_size] => 150x150x150 ) Array ( [clientId] => 23 [clientName] => EG [sizeId] => 1 [sample] => 6 [monitorId] => 354 [monitor_label] => C82 [remark] => 15% EPP [slump] => 165 [casting_date] => 2017-03-21 [casting_time] => 17:30:00 [grade] => 25 [mix_design] => p [p_title] => SA [p_alias] => SA [techId] => 2 [tech_name] => HF [c_size] => 150x150x150 ) Array ( [clientId] => 23 [clientName] => EG [sizeId] => 1 [sample] => 6 [monitorId] => 355 [monitor_label] => C83 [remark] => 15% EPP [slump] => 200 [casting_date] => 2017-03-21 [casting_time] => 18:40:00 [grade] => 25 [mix_design] => p [p_title] => SA [p_alias] => SA [techId] => 3 [tech_name] => HVJ [c_size] => 150x150x150 ) above is the result of my database query, to find a certain client based on its ID. then i group the data based on the grade and mix_design with the following code //group by the concrete grade public function details_client2($id) { $q = $this->find(['clientId=?',$id], [ 'order' => 'casting_date DESC' ] ); $data = []; foreach($q as $d) { $data[$d['grade'].$d['mix_design']][] = $d->cast(); } ksort($data); //sort the data based on grade. Lowest to Highest return $data; } **i am using Fat Free Framework to get the result data, i traverse again the grouped array by grade, taking its monitorId and making another call to database to retrieve the result from a view with this function //retrieve data based on monitorId value // if 'age' contain same value, calculate the average strength // and group all data based on 'age' public function graphData($id) { //set virtual field for average strength columns $this->avg_str = 'AVG(strength)'; $find = $this->find( ['monitorId=?',$id], ['group' => 'age'] ); $data = []; foreach($find as $gData) { $data[] = ['x'=> $gData['age'],'y'=> $gData['avg_str']]; } return $data; } at the same time, i group again the data based on its age, since later i am using the same data to plot a graph. I am not really grouping, just averaging the same age data. +------+------------+--------+----------+-----------+----------+---------+-------------+------+ | mrId | date_test | c_load | c_weight | monitorId | strength | density | str_percent | age | +------+------------+--------+----------+-----------+----------+---------+-------------+------+ | 1556 | 2017-03-22 | 70.0 | 7750 | 351 | 3.11 | 2.296 | 8.89 | 1 | | 1598 | 2017-03-23 | 235.0 | 7750 | 351 | 10.44 | 2.296 | 29.84 | 2 | | 1634 | 2017-03-24 | 380.0 | 7660 | 351 | 16.89 | 2.270 | 48.25 | 3 | | 1747 | 2017-03-28 | 635.0 | 7900 | 351 | 28.22 | 2.341 | 80.63 | 7 | | 2282 | 2017-04-18 | 1155.0 | 8090 | 351 | 51.33 | 2.397 | 146.67 | 28 | | 2283 | 2017-04-18 | 870.0 | 7990 | 351 | 38.67 | 2.367 | 110.48 | 28 | | 2284 | 2017-04-18 | 935.0 | 7950 | 351 | 41.56 | 2.356 | 118.73 | 28 | +------+------------+--------+----------+-----------+----------+---------+-------------+------+ above is an example of return data from view all of the array of data then glued together with this function foreach($monitors as $grade => $data ) { foreach($data as $d) { $graph[$grade][] = [ 'id' => $d['monitorId'], 'label' => $d['monitor_label'], 'casting' => date('d M Y',strtotime(trim($d['casting_date']))), 'data' => $gr->graphData($d['monitorId']) ]; } } to give make this array Array ( [25p] => Array ( [0] => Array ( [id] => 353 [label] => C81 [casting] => 21 Mar 2017 [data] => Array ( [0] => Array ( [x] => 1 [y] => 6.220000 ) [1] => Array ( [x] => 2 [y] => 10.220000 ) [2] => Array ( [x] => 7 [y] => 21.440000 ) [3] => Array ( [x] => 28 [y] => 30.780000 ) ) ) [1] => Array ( [id] => 354 [label] => C82 [casting] => 21 Mar 2017 [data] => Array ( [0] => Array ( [x] => 1 [y] => 8.000000 ) [1] => Array ( [x] => 3 [y] => 20.890000 ) [2] => Array ( [x] => 6 [y] => 30.670000 ) [3] => Array ( [x] => 7 [y] => 32.555000 ) [4] => Array ( [x] => 28 [y] => 51.110000 ) ) ) [2] => Array ( [id] => 355 [label] => C83 [casting] => 21 Mar 2017 [data] => Array ( [0] => Array ( [x] => 1 [y] => 7.110000 ) [1] => Array ( [x] => 3 [y] => 19.780000 ) [2] => Array ( [x] => 6 [y] => 23.560000 ) [3] => Array ( [x] => 7 [y] => 32.225000 ) [4] => Array ( [x] => 15 [y] => 38.890000 ) ) ) ) ) Quote Link to comment Share on other sites More sharing options...
requinix Posted July 13, 2017 Share Posted July 13, 2017 Then I don't really see much room for improvement, as far as a way to get data into the output more easily. echo '<td>'.$mdata[$d] ?? 'N/A'.'</td>'; this should be the same as echo isset($mdata[$d]) ? '<td>'.$mdata[$d].'</td>' : '<td> N/A </td>'; but the first code will not show N/A but the second do show N/A Because they are not the same. . gets evaluated before ?? so the first code is the same as writing echo ('<td>'.$mdata[$d]) ?? ('N/A'.'</td>');which is obviously not what you want. Use parentheses. echo '<td>'.($mdata[$d] ?? 'N/A').'</td>'; Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.