Jump to content

creating table from array with different value


Go to solution Solved by requinix,

Recommended Posts

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


 

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?

  • Solution

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.

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.

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?

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
                                )

                        )

                )

        )

)

 

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>';
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.