I need to create and populate a table with a array... for now with some help from the bloggers goes like this:
<?php
$details = array(
1 => array(
1 => 1000,
2 => 'Company A',
3 => '2014-05-10',
4 => '10:00:00',
5 => '15:00:00',
),
2 => array(
1 => 2000,
2 => 'Company A',
3 => '2014-05-11',
4 => '10:00:00',
5 => '15:00:00',
),
3 => array(
1 => 3000,
2 => 'Company B',
3 => '2014-05-10',
4 => '10:00:00',
5 => '15:00:00',
),
4 => array(
1 => 4000,
2 => 'Company B',
3 => '2014-05-11',
4 => '16:00:00',
5 => '19:00:00',
)
);
// Format our data into something we can use more easily
$flight_dates = array();
$times = array();
$dates = array();
foreach ($details as $flight_details) {
$company_name = $flight_details[2];
$date = $flight_details[3];
$time = $flight_details[4] . ' - ' . $flight_details[5];
// Keep a unique record of each date, and the times of flights
$dates[$date] = 1;
$times[$time] = 1;
// Record which date/time each company is flying
$flight_dates[$date][$time][] = $company_name;
}
// Create the table header
$html = '<table border="1">';
$html .= '<thead>';
$html .= '<tr>';
$html .= '<th> </th>';
foreach ($dates as $date => $value1) {
$html .= '<th>' . $date . '</th>';
}
$html .= '</tr>';
// Create the rows in the table
foreach ($times as $time => $value1) { // Loop through each flight time
$html .= '<tr>';
$html .= '<td>' . $time . '</td>'; // The first column is always the time
foreach ($dates as $date => $value2) { // Loop through each date
if (!empty($flight_dates[$date][$time])) { // Check if flights exist at the current time
$html .= '<td>' . implode(', ', $flight_dates[$date][$time]) . '</td>'; // List companies
} else { // No flights
$html .= '<td> </td>'; // Leave cell blank
}
}
$html .= '</tr>';
}
$html .= '</table>';
echo $html;
?>
The result is this:
|....................|.. 2014-05-10 ........| 2014-05-11|
|10:00:00 - 15:00:00 | Company A, Company B | Company A |
|16:00:00 - 19:00:00 |......................| Company B |
I'm looking to get this:
|....................|2014-05-10 | 2014-05-11|
|10:00:00 - 15:00:00 | Company A | Company A |
|10:00:00 - 15:00:00 | Company B |...........|
|16:00:00 - 19:00:00 |...........| Company B |
In my idea the deal is: $times should have all the times for all the $flight_details array, and then we populate, will create a row for each $times record, that way we don't need to implode, just put the direct value off the array. The problem is to achieve this...
If you want such format, first off, you need to separate the headers, 2014-05-10 ... etc since they are above. Then you need to take care of the format. The key is: every time slot assign it to the company. Consider this example:
<?php
$details = array( 1 => array( 1 => 1000, 2 => 'Company A', 3 => '2014-05-10', 4 => '10:00:00', 5 => '15:00:00', ), 2 => array( 1 => 2000, 2 => 'Company A', 3 => '2014-05-11', 4 => '10:00:00', 5 => '15:00:00', ), 3 => array( 1 => 3000, 2 => 'Company B', 3 => '2014-05-10', 4 => '10:00:00', 5 => '15:00:00', ), 4 => array( 1 => 4000, 2 => 'Company B', 3 => '2014-05-11', 4 => '16:00:00', 5 => '19:00:00', ), 5 => array( 1 => 5000, 2 => 'Company C', 3 => '2014-05-10', 4 => '10:00:00', 5 => '15:00:00', ), 6 => array( 1 => 5000, 2 => 'Company D', 3 => '2014-05-12', 4 => '10:00:00', 5 => '15:00:00', ),);
//properly sort the raw data
// get headers
$header_dates = array();
foreach($details as $value) {
$header_dates[] = $value[3];
}
$header_dates = array_unique($header_dates);
// reformat main data companies
foreach($details as $key => $value) {
$time = "$value[4] - $value[5]"; // use this as key
foreach($header_dates as $date) {
// simple initialization
if(!isset($final[$value[2]][$time][$date])) $final[$value[2]][$time][$date] = '';
}
$final[$value[2]][$time][$value[3]] = $value[2];
// then set them accordingly to their date and time
}
?>
<!-- format them inside the table -->
<table border="1" cellpadding="10">
<!-- print the headers -->
<thead><tr><td></td><?php foreach($header_dates as $value): ?><th><?php echo $value; ?></th><?php endforeach; ?></tr></thead>
<tbody>
<?php foreach($final as $key => $data): ?>
<?php foreach($data as $index => $element): ?>
<tr><td><?php echo $index; ?></td> <!-- loop they time -->
<?php foreach($element as $v):?>
<td><?php echo $v; ?></td> <!-- values (Company A, ...) -->
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
<?php endforeach; ?>
</tbody>
</table>
Sample Output
For the result to come like your expected one, you need to give:
<td>{explode("," $company_name)[0]}</td>
<td>{explode("," $company_name)[1]}</td>
In the headers, you need to give this way:
<td colspan="2">{$date}</td>
Note: The code I have provided is just a pseudo code. You need to write your own code. We can just guide you!
Related
I have been stuck for days on this 'little' problem.
I have one array which contains specific data:
$data = array(
0 => array('id' => 8, 'month' => 1, 'cost' => 12500),
1 => array('id' => 8, 'month' => 2, 'cost' => 14200),
2 => array('id' => 9, 'month' => 1, 'cost' => 23000),
3 => array('id' => 9, 'month' => 2, 'cost' => 18000),
);
And this is the html table results i need to get:
Id Jan Feb Mar Apr May
8 12,500 14,200 10,200 10,300 11,000
9 23,000 18,000 21,320 10,642 14,636
How i can sort array to display this data in html table on view.ctp ?
I have tried using foreach loops but i really don't know how to put unique months and unique id like it is displayed above. I'm using CakePHP 2.x technology.
I appreciate every help. Thank you
Loop over your array and group into a new array based on the ID. Assign month=cost key-value pairs, using IDs as the grouping keys of your multidimensional array.
$by_id = [];
foreach($data as $x) {
$by_id[$x['id']][$x['month']] = $x['cost'];
// e.g. $by_id[8][2] = 14200;
}
This will turn your sample data into the following array:
array(2) {
[8] · array(2) {
[1] · int(12500)
[2] · int(14200)
}
[9] · array(2) {
[1] · int(23000)
[2] · int(18000)
}
}
That should be much easier to turn into a HTML table. For example like this:
$html = [];
$html[] = '<table>';
$html[] = '<tr><th>ID</th><th>Jan</th><th>Feb</th></tr>';
foreach($by_id as $id => $months) {
$html[] = '<tr>';
$html[] = "<td>{$id}</td>";
foreach($months as $month => $cost) {
$html[] = "<td>{$cost}</td>";
}
$html[] = '</tr>';
}
$html[] = '</table>';
echo implode("\n", $html);
I trust the code is clear enough without elaborate comments. Add months to the table header as necessary. Use e.g. number_format for $cost to format your monies. Be aware that the sample code above doesn't account for possible missing months for a given ID, it assumes symmetric data. Add checks and remedies if necessary. See demo at https://3v4l.org/7CFRf.
You should use a 2D array to display that kind of table.
Then the $data array might be like this:
$data = array(
0 => array('id' => 8, 'costData' => array(
0 => array('month' => 1, 'cost' => 12500),
1 => array('monnt' => 2, 'cost' => 14200)
),
1 => array('id' => 9, 'costData' => array(
0 => array('month' => 1, 'cost' => 23000),
1 => array('month' => 2, 'cost' => 18000)
)
);
To revert the $data array like this, the code below will be needed.
<?php
$newData = array();
for($i = 0; $i < count($data); $i++)
{
$newItem = array('id' => $data[$i]['id'], 'costData' => array(
'month' => $data[$i]['month'],
'cost' => $data[$i]['cost']
));
for($j = $i + 1; $j < count($data); $j++)
{
if($data[$j]['id'] == $data[$i]['id']) {
$newItem['costData'][] = array('month' => $data[$j]['month'], 'cost' => $data[$j]['cost']);
array_splice($data, $j, 1);
$j--;
}
}
$newData[] = $newItem;
}
Using new data Array, you can make your html page like this.
$html = '';
for($i = 0; $i < count($newData); $i++)
{
$html .= '<tr>';
$html .= '<td>'.($newData[$i]['id']).'</td>';
for($j = 0; $j < count($newData[$i]['costData']); $j++) {
$html .= '<td>'.($newData[$i]['costData'][$j]).'</td>';
// you can do some operations if there are missing months to leave blank td tags..
}
// fill the missing months to fill the td tags.
}
You could use a combination of the array_column() and array_sum() functions:
$data = array(
array('id' => 8, 'month' => 1, 'cost' => 12500),
array('id' => 8, 'month' => 2, 'cost' => 14200),
array('id' => 9, 'month' => 1, 'cost' => 23000),
array('id' => 9, 'month' => 2, 'cost' => 18000),
);
$result = array();
foreach ($data as $row) {
$result[$row['id']][$row['month']] = $row['cost'];
}
// Sum the costs for each month
$months = array_column($data, 'month');
$result = array_map(function($v) use ($months) {
return array_sum(array_intersect_key($v, array_flip($months)));
}, $result);
print_r($result);
This will output:
Array
(
[8] => Array
(
[1] => 12500
[2] => 14200
)
[9] => Array
(
[1] => 23000
[2] => 18000
)
)
Consider the following $data array:
Array
(
[0] => Array
(
[code] => 20
[name] => Name 1
[month] => 4
[cost] => 100
..
..
)
[1] => Array
(
[code] => 30
[name] => Name 2
[month] => 3
[cost] => 120
..
..
)
[1] => Array
(
[code] => 30
[name] => Name 2
[month] => 6
[cost] => 180
..
..
)
..
..
)
Each array can have unknown number of codes. Each code has a different month ID. I want to sort and display the data so that there is just one row for the each code, and then in that row, display the value of the [cost] in the column number equal to the month. For example:
Column 1 2 3 4 5 6 7 8 9 10 11 12
Name 1 100
Name 2 120 180
Here's what I'm trying:
In order to find out how many rows should be printed, I fetch the unique code values:
$codes = array();
foreach( $data as $row ){
if ( in_array($row['code'], $codes) ) {
continue;
}
$codes[] = $row['code'];
}
Next, I use a loop to print the rows:
foreach( $codes as $code ){
//print 12 columns for each othe row
for ($i = 1; $<=12; $i++) {
//display column value if the code is same as the row
//and the month value is same as $i
//here's the problem
if (( $data['code'] == $code ) &&( $data['month'] == $i )) {
echo $data['cost'];
}
}
}
Problem/Question:
Do I need to put another loop inside the for loop to check if the $data['code'] == $code ? Or how can I do that?
I would use one loop to re-index the array:
$list = $codes = [];
for ($array as $item){
$list[$item['code']][$item['month']] = $item;
$codes[$item['code']] = $item['name'];
}
then use two loops to print:
for ($codes as $code => $codeName){
echo '<tr><th>', $codeName, '</th>';
for (range(1, 12) as $month){
echo '<td>', ($list[$code][$month]['cost'] ?? ''), '</td>;
}
echo '</tr>', "\n";
}
I really do not like the idea of if()s inside the loops.
I would suggest that you preprocess your data to a structured array first and then you print it, for example, indexed by code with a structure like:
[
['the code'] => [
'name' => '',
'months' => [
'6' => // cost
]
]
]
You can do it like this:
$items = [
[
'code' => 20,
'name' => 'Name 1',
'month' => 4,
'cost' => 100,
],
[
'code' => 30,
'name' => 'Name 2',
'month' => 3,
'cost' => 120,
],
[
'code' => 30,
'name' => 'Name 2',
'month' => 6,
'cost' => 180,
],
];
$sortedItems = [];
foreach ($items as $item) {
if (!isset($sortedItems[$item['code']])) {
$sortedItems[$item['code']] = [
'name' => $item['name'],
'months' => [],
];
}
$sortedItems[$item['code']]['months'][$item['month']] = $item['cost'];
}
You can the print it using a function similar to this:
function printItemsOf(array $list) {
echo '<table>';
// print header
echo '<tr>';
echo '<td>Column</td>';
for ($i = 1; $i <= 12; $i++) {
echo '<td>' . $i . '</td>';
}
echo '</tr>';
// print items
foreach ($list as $code => $item) {
echo '<tr>';
echo '<td>' . $item['name'] . '</td>';
for ($i = 1; $i <= 12; $i++) {
if (!isset($item['months'][$i])) {
echo '<td></td>';
} else {
echo '<td>' . $item['months'][$i] . '</td>';
}
}
echo '</tr>';
}
echo '</table>';
}
Which outputs:
<table border="1"><tr><td>Column</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>10</td><td>11</td><td>12</td></tr><tr><td>Name 1</td><td></td><td></td><td></td><td>100</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>Name 2</td><td></td><td></td><td>120</td><td></td><td></td><td>180</td><td></td><td></td><td></td><td></td><td></td><td></td></tr></table>
I have the following multidimensional array.
$dog_treats=array(
array(
'Rupert' = array(
'Breed' => 'German Shepherd',
'treats' = array(
0 => 3,
1 => 2,
2 => 6
),
),
'Zeus' = array(
'Breed' => 'Golden Retreiver',
'treats' = array(
0 => 5,
1 => 4,
2 => 1,
3 => 2
),
),
),
);
The syntax is a bit off but that's how it looks like. The code that creates it is:
$dog_treats['Rupert']['Breed'] = 'German Shepherd';
$dog_treats['Rupert']['treats'][0] = 3;
$dog_treats['Rupert']['treats'][1] = 2;
$dog_treats['Rupert']['treats'][2] = 6;
$dog_treats['Zeus']['Breed'] = 'Golden Retreiver';
$dog_treats['Zeus']['treats'][0] = 5;
$dog_treats['Zeus']['treats'][1] = 4;
$dog_treats['Zeus']['treats'][2] = 1;
$dog_treats['Zeus']['treats'][3] = 2;
For each dog I want to get the maximum and minimum number of treats they ate that day. How do I do this? Thanks
Rupert max = 6 min = 2
Zeus max = 5 min = 1
basically:
foreach ($dog_treats as $k=>$v){
echo $k.'<br>';
echo "max: ". max($dog_treats[$k]['treats']).'<br>';
echo "min: ". min($dog_treats[$k]['treats']).'<br>';
}
demo: http://codepad.viper-7.com/BGeMGx
OR
foreach ($dog_treats as $k=>$v){
echo $k.'<br>';
echo "max: ". max($v['treats']).'<br>';
echo "min: ". min($v['treats']).'<br>';
}
If you want to store the min/max treats in the array you could use array_walk and apply those values:
array_walk($dogs, function(&$dog) {
$dog['min'] = min($dog['treats']);
$dog['max'] = max($dog['treats']);
});
If you just want to the print the min/max, you could use a foreach loop and simply echo:
echo 'min: ' . min($dog['treats']);
If you want to define the array at once then you can use the following code:
$dog_treats = array(
array(
'Rupert' => array(
'Breed' => 'German Shepherd',
'treats' => array(
0 => 3,
1 => 2,
2 => 6
),
),
'Zeus' => array(
'Breed' => 'Golden Retreiver',
'treats' => array(
0 => 5,
1 => 4,
2 => 1,
3 => 2
),
),
),
);
foreach($dog_treats as $key) {
foreach($key as $dog => $value) {
echo 'Dog: '.$dog.', Max: '.max($value['treats']).', Min: '.min($value['treats']).'<br />';
}
}
Results:
Dog: Rupert, Max: 6, Min: 2
Dog: Zeus, Max: 5, Min: 1
I have two db tables as follow:
Categories Table
--- ID --- Name -- GroupID
1 Cat 1 0
2 Cat 2 0
3 Side 1 1
4 Side 2 1
Product Table
--- ID --- Name – CatID – CatID2
1 P1 1 3
2 P2 1 4
3 P4 2 3
4 P3 2 4
5 P5 1 4
Based on above table i would to output in following format:
All Categories with GroupID 0 to be column names ( table header)
All Categories with GroupID 1 first column/row
Product's appear in each row depending on group 0 an 1
Sample output:
Cat 1 Cat 2
Side 1 P1 P4
Side 2 P2,P5 P3
I am not sure if the table structure is wrong, i can get a list categories and products but I’m unsure how to output the above table.
here the solution i came up with, i have omitted database stuff to make it simpler.
Data is hardcoded arrays:
$cats = array(
array(
'id' => 1,
'name' => 'cat 1 '
),array(
'id' => 2,
'name' => 'cat 2 '
),array(
'id' => 3,
'name' => 'cat 3 '
)
);
$side = array(
array(
'id' => 5,
'name' => 'side 1 '
),array(
'id' => 4,
'name' => 'side 2 '
),array(
'id' => 6,
'name' => 'side 3 '
)
);
$products = array(
array(
'id' => 5,
'name' => 'p1',
'cat' => 1,
'side' => 6,
),array(
'id' => 5,
'name' => 'p2',
'cat' => 1,
'side' => 6,
),array(
'id' => 6,
'name' => 'p3',
'cat' => 2,
'side' => 5,
),array(
'id' => 7,
'name' => 'p4',
'cat' => 2,
'side' => 6,
)
);
Next this function used to search both cat and side arrays and check if product matches.
function search_p($array, $key, $value, $key2, $value2)
{
$results = array();
if (is_array($array) ) {
if (isset($array[$key]) && $array[$key] == $value && isset($array[$key2]) && $array[$key2] == $value2) {
$results[] = $array;
}
foreach ($array as $subarray) {
$results = array_merge($results, search_p($subarray, $key, $value,$key2, $value2));
}
}
return $results;
}
To output the table i did the following:
<table>
<tr>
<th></th>
<?php
foreach($cats AS $c){
echo '<th>'.$c['name'].'</th>';
}
?>
</tr>
<?php
foreach($side AS $a){
echo '<tr><td>'.$a['name'].'</td>';
foreach($cats AS $c){
echo '<td>';
$p = search_p($products, 'cat', $c['id'], 'side', $a['id']);
foreach($p AS $pc){
echo '-- '.$pc['name'].' -- ';
}
echo '</td>';
}
echo '</tr>';
}
?>
</table>
Hello I got a question: I want to make a table of these two arrays. In the first column I want the players name, second column the score and the third column the average of the score. I only get the players in the table and it is repeating itself. I dont know how to make it work. I know the value in the foreach is the players so I knew it would repeat itself but how can I fix this?
<?php
$aScore = array (1 => 0, 2 => 20, 3 => 4, 4 => 23, 5 => 5, 6 => 4);
$aPlayers = array (1 => 'Jansen', 2 => 'Boularus', 3 => 'Rintintin', 4 => 'Chavez', 5 => 'Zomers', 6 => 'Tahamata');
echo '<table border="1">';
echo '<tr><td>Player</td><td>Score</td><td>Average score</td></tr>';
foreach($aPlayer as $key => $value)
{
echo '<tr><td>'.$value.'</td><td>'.$value.'</td><td>'.$value.'</td></tr>';
};
echo '</table>';
?>
Just try with:
foreach($aPlayers as $key => $value)
{
echo '<tr><td>'.$value.'</td><td>'. $aScore[$key] .'</td><td>'. $aAverageScore[$key] .'</td></tr>';
}
There is no $aAverageScore variable in your question but I assume that you will know what to put here instead.
However you should store your data in multidimentional associative array, like:
$players = array(
array(
'name' => 'Jansen',
'score' => 0,
'average' => 0
),
array(
'name' => 'Boularus',
'score' => 20,
'average' => 20
),
// ...
);
And loop it with:
foreach ($players as $player) {
echo '<tr><td>' . $player['name'] . '</td><td>' . $player['score'] . '</td><td>' . $player['average'] . '</td></tr>';
}
Use a simple for loop instead of a foreach:
for ($k=1; $k<=count($aPlayer); $k++) {
echo '<tr><td>'.$aPlayer[$k].'</td><td>'.$aScore[$k].'</td><td></td></tr>';
}