Moving empty values of an array to the last position - php

I'm pulling an array from an external API, And I've got some help with usort on here, And It pushes it to the bottom, and empty values are on top. I tried using unset but that just emptied out my entire realArrival values.
e.g.
$fromThis = array(
"realArrival": "",
"realArrival": "Confirm. 06:18",
"realArrival": "Confirm. 06:19"
);
Into:
$intoThis = array(
"realArrival": "Confirm. 06:18",
"realArrival": "Confirm. 06:19",
"realArrival": ""
);
Here is my code on how I tried to do it. I'm sure you are shaking your head at this but here it goes.
$url = 'http://apis.is/flight?language=en&type=arrivals';
$json = file_get_contents($url);
$results = json_decode($json, TRUE);
$results = $results['results'];
function cmp($a, $b) {
return strcmp($a['realArrival'], $b['realArrival']);
}
//Sort Time
usort($results, "compare_time");
function compare_time($a,$b) {
$splitA= count(explode(' ',$a['realArrival']));
$splitB= count(explode(' ',$a['realArrival']));
if($splitA==2 && $splitB==2)
{
$first_time = strtotime(explode(' ',$a['realArrival'])[1]);
$second_time = strtotime(explode(' ',$b['realArrival'])[1]);
if($first_time==$second_time)
{
return strcmp($b['realArrival'], $a['realArrival']);
}
return ($second_time < $first_time) ? 1: 0;
}
return strcmp($a['realArrival'], $b['realArrival']);
}
echo '<table class="highlight bordered responsive-table grey darken-2 col s6">';
echo "<tr>";
echo '<th>Date</th>';
echo '<th>Flight Number</th>';
echo '<th>Airline</th>';
echo '<th>From</th>';
echo '<th>Schedule. Time</th>';
echo '<th>Status</th>';
echo "</tr>";
foreach ($results as $item => $val) {
echo "<tr>";
echo '<td>'.$val['date'].'</td>';
echo '<td>'.$val['flightNumber'].'</td>';
echo '<td>'.$val['airline'].'</td>';
echo '<td>'.$val['from'].'</td>';
echo '<td>'.$val['plannedArrival'].'</td>';
// HERE I TRIED TO TARGET THE EMPTY VALUES
if ($val === "") {
unset($results[$item]);
$results[] = $val;
echo '<td style="font-weight: bold;">'.$val['realArrival'].'</td>';
}
echo '</tr>';
}

I know this might seem clunky, but you could always just do something like...
$items_with_real_arrivals = array();
$items_without_real_arrivals = array();
foreach ($results as $item => $val) {
if ($item[‘realArrival’] === "") { $items_without_real_arrivals.push($item); }
else $items_with_real_arrivals.push($item);
}
$reordered_items = array();
for ($i=0; $i<count($items_with_real_arrivals); $i++) {
$reordered_items.push($item);
}
for ($i=0; $i<count($items_without_real_arrivals); $i++) {
$reordered_items.push($item);
}
foreach ($reordered_items as $item => $val) {
echo "<tr>";
echo ' <td>'.$val['date'].'</td>';
echo ' <td>'.$val['flightNumber'].'</td>';
echo ' <td>'.$val['airline'].'</td>';
echo ' <td>'.$val['from'].'</td>';
echo ' <td>'.$val['plannedArrival'].'</td>';
echo ' <td style="font-weight:bold;">' . $val['realArrival'].'</td>';
echo '</tr>';
}

Related

XML: Show two child nodes with the same name in php

I have a problem with showing my xml into a php page. I have an xml that looks like this (obviously its only a part of it because it really to long to post it all).
It all goes well until it cames to the "genre", I have two values for it and I don't know how to show them at the same time.
<movie>
<id>4441</id>
<title>Rudderless</title>
<title_long>Rudderless (2014)</title_long>
<year>2014</year>
<rating>7.5</rating>
<runtime>105</runtime>
<genres>
<genre>Comedy</genre>
<genre>Drama</genre>
</genres>
</movie>
(an important thing to notice is that not every movie will have two genre, sometimes there is only one and sometime two or three)
This is my code right now
$genere = array();
foreach ($xml->data->movies->movie->genres as $row) {
foreach ($row->children() as $key => $val) {
if ($key == "genre") {
$genere[] = $val;
}
}
}
//and then I'll print
for ($i = 0; $i < 20 ; $i++) {
echo "<div class=text><b>" . $genere[$i] . "</b></div>";
}
When I'm doing this it will print only for the first item of the array, and the others just give me a "Notice: Undefined offset: 1 in /path/ on line 53"
I've tried to follow some guides but it was a failure
What am I doing wrong?
/--Edit--/
<?php
$xml = simplexml_load_file("https://yts.to/api/v2/list_movies.xml")
$titolo = array();
$locandina = array();
$anno = array();
$durata = array();
$genere = array();
foreach ($xml->data->movies->movie as $element)
{
foreach($element->children() as $key => $val)
{
$chiave = $key;
$valore = $val;
if ($key == "title")
{
$titolo[] = $val ;
}
if ($key == "medium_cover_image")
{
$locandina[] = $val ;
}
if ($key == "year")
{
$anno[] = $val ;
}
if ($key == "runtime")
{
$durata[] = $val;
}
}
}
foreach ($xml->data->movies->movie->genres as $row)
{
foreach($row->children() as $key => $val)
{
if ($key == "genre")
{
$genere[] = $val;
}
}
}
var_dump($genere);
for ($i=0 ; $i<20 ; $i++)
{
echo "<div class=totbox>";
echo "<div class=box><img src=" . $locandina[$i] . "></div>";
echo "<div class=text><b>" . $titolo[$i] . "</b> - " . $anno[$i] . "</div>";
echo "<div class=text><b>" . $genere[$i] . "</b></div>";
echo "<div class=text><b> Durata:" . $durata[$i] . "</b></div>";
echo "</div>";
}
?>
UPDATED - Code fixed. Please, try now.
<?php
$xml = simplexml_load_file("https://yts.to/api/v2/list_movies.xml")
$titolo = array();
$locandina = array();
$anno = array();
$durata = array();
$genere = array();
$i = 0;
foreach ($xml->data->movies->movie as $element) {
foreach ($element->children() as $key => $val) {
$chiave = $key;
$valore = $val;
if ($key == "title") {
$titolo[] = $val;
}
if ($key == "medium_cover_image") {
$locandina[] = $val;
}
if ($key == "year") {
$anno[] = $val;
}
if ($key == "runtime") {
$durata[] = $val;
}
if ($key == "genres") {
for($g = 0; $g < count($xml->data->movies->movie[$i]->genres->genre); $g++) {
$genere[$i][] = $xml->data->movies->movie[$i]->genres->genre[$g];
}
}
}
$i++;
}
for ($i = 0; $i < count($titolo); $i++) {
echo "<div class=totbox>";
if (isset($locandina[$i])) {
echo "<div class=box><img src=" . $locandina[$i] . "></div>";
}
echo "<div class=text><b>" . $titolo[$i] . "</b> - " . $anno[$i] . "</div>";
foreach ($genere[$i] as $genResult) {
echo "<div class=text><b>" . $genResult . "</b></div>";
}
echo "<div class=text><b> Durata:" . $durata[$i] . "</b></div>";
echo "</div>";
}
I hope this helps!
Look on my code, based on yours. PHP file:
<?php
$xml = new SimpleXMLElement(file_get_contents('test.xml'));
$genere = array();
foreach ($xml->genres as $row) {
foreach ($row->children() as $key => $val) {
if ($key == "genre") {
$genere[] = $val;
}
}
}
//and then I'll print
foreach ($genere as $genre) {
echo "<div class=text><b>" . $genre . "</b></div>";
}
XML file:
<movie>
<id>4441</id>
<title>Rudderless</title>
<title_long>Rudderless (2014)</title_long>
<year>2014</year>
<rating>7.5</rating>
<runtime>105</runtime>
<genres>
<genre>Comedy</genre>
<genre>Drama</genre>
</genres>
</movie>
Its work fine, test it.
Based on your full xml file, look on this:
<genres>
<genre>Horror</genre>
</genres>
You have only one genre on first position, so its work fine. You need to loop on movie tag first, not genres. So put your genre tag inside movie foreach.
Like:
foreach($element->children() as $key => $val)
{
if ($key == "genres")
{
// your loop, based on $val variable!
}

Sort PHP Array Based on Number

I am trying to get a Downloads page working. I get a build number and details from a file, and I want to sort the array with that build number, currently 0.0.2 is above 1.0.3, and it will always keep the build number as it ascends. You can see the page at http://tattyseal.com/files/zaet
<?php
echo "<table border=0 style='text-align:left;border-spacing: 40px 0;'>";
echo "<tbody>";
echo "<img src='logoFile.png'/>";
echo "<h2>Promotions</h2>";
echo "<tr>";
echo "<th>Promotion</th>";
echo "<th>Version</th>";
echo "<th>Minecraft</th>";
echo "<th>Downloads</th>";
echo "</tr>";
echo "<tr>";
echo "<td>1.7.2-Recommend</td>";
echo "<td>0.0.2</td>";
echo "<td>1.7.2</td>";
echo "<td>(<a href='http://ts.tattyseal.com:8080/job/Zaet/2/artifact/build/libs/Zaet-dev-0.0.2.jar'>Universal</a>) (<a href='http://ts.tattyseal.com:8080/job/Zaet/2/artifact/build/libs/Zaet-dev-0.0.2.jar'>Deobf</a>) (<a href='http://ts.tattyseal.com:8080/job/Zaet/2/artifact/build/libs/Zaet-src-0.0.2.jar'>Src</a>)";
echo "</tr>";
echo "</tbody>";
echo "</table>";
echo "<table border=0 style='text-align:left;border-spacing: 40px 0;'>";
echo "<tbody>";
echo "<tr>";
echo "<h2>1.7.2 Downloads - Anything that is not Recommended can be unstable, there is a possibility of World Corruption</h2>";
echo "<th>Version</th>";
echo "<th>Minecraft</th>";
echo "<th>Time</th>";
echo "<th>Downloads</th>";
echo "</tr>";
$information = array();
$iterator = new RecursiveDirectoryIterator('versions');
foreach(new RecursiveIteratorIterator($iterator) as $filename => $file)
{
if (strpos($filename,'info') !== false)
{
array_push($information, file_get_contents($filename));
}
}
sort($information);
$information = array_reverse($information);
$info = $information;
$versions = array();
foreach($info as $i)
{
$array = explode(",", $i);
foreach($array as $line)
{
if(strpos($line, 'version') !== false)
{
if(strpos($line, 'mcversion') === false)
{
$array2 = explode(": ", $line);
array_push($versions, $array2[1]);
}
}
}
}
foreach($information as $info)
{
$array = explode(",", $info);
$mcversion = "";
$version = "";
$date = "";
$build = "";
foreach($array as $line)
{
if(strpos($line, 'mcversion') !== false)
{
$array3 = explode(": ", $line);
$mcversion = $array3[1];
}
if(strpos($line, 'version') !== false)
{
$array3 = explode(": ", $line);
$version = $array3[1];
}
if(strpos($line, 'date') !== false)
{
$array3 = explode(": ", $line);
$date = $array3[1];
}
if(strpos($line, 'build') !== false)
{
$array3 = explode(": ", $line);
$build = $array3[1];
}
}
echo "<tr><td>$version</td><td>$mcversion</td><td>$date</td><td>" . "(<a href='http://ts.tattyseal.com:8080/job/Zaet/$build/changes'>Changelog</a>) (<a href='http://ts.tattyseal.com:8080/job/Zaet/$build/artifact/build/libs/Zaet-dev-0.0.$build.jar'>Deobf</a>) (<a href='http://ts.tattyseal.com:8080/job/Zaet/$build/artifact/build/libs/Zaet-src-0.0.$build.jar'>Src</a>) (<a href='http://ts.tattyseal.com:8080/job/Zaet/$build/artifact/build/libs/Zaet-mod-0.0.$build.jar'>Universal</a>)</td></tr>";
}
echo "</tbody>";
echo "</table>";
?>
Thanks

Calculate max, min, and average for every column in a 2D array

I'm calculating the average,min,max for each column.
The 16th column value is coming wrong for max and min. Average is working perfectly fine, but wrong only for the last column with large arrays -- I also get a notice error.
My code:
mysql_connect("localhost", "root", "") or
die("Could not connect: " . mysql_error());
mysql_select_db("db");
$qry = mysql_query("select blob_field from table where id=1");
$arr = mysql_fetch_row($qry) ;
$rt = explode("\n",$arr[0]);
$header_arr1 = explode(',',$rt[0]);
$header1 = array();
$channels = count($header_arr1)-2 ;
$header1[] = join(',', array_slice($header_arr1, 2));
//Only Header
$arr_values = array_values($rt);
$array_slice = array_slice($arr_values, 1);
echo "<pre>";
//print_r($array_slice);
$result_array = array();
for($i=0;$i<count($array_slice);$i++)
{
//echo $i;
$result_array[] = join(',',array_slice(explode(',', $array_slice[$i]), 2));
}
//print_r($result_array);
//$array_combined = array_merge($header1,$result_array);
$token = array( 'Average', 'Max', 'Min');
foreach($result_array as $key=>$val)
{
$res_arr[] = explode(",",$val);
}
$avArray = array();
$res_arr= array(
0=>array(1,2,3,6,7,8,9,11,33,44,55,66,77,88,16,18),
1=>array(17,52,38,666,79,8,9,15,33,44,55,66,76,88,16,18),
2=>array(17,562,538,7666,579,688,9,15,933,44,55,660,76,808,106,108),
);
foreach ($res_arr as $k=>$subArray)
{
foreach ($subArray as $id=>$value)
{
//print_r($id);
$avArray[$id] += $value/count($res_arr); //Notice: Undefined offset: 3
}
}
$token = array( 'Average', 'Max', 'Min');
$num = $avArray;
$tc=16;
?>
<table border="1" style="border-collapse: collapse;">
<thead>
<tr>
<th>Channels</th>
<?php for($j=0;$j<=$tc-1;$j++):?>
<th>CH<?= $j+1;?></th>
<?php endfor;?>
</tr>
</thead>
<tbody>
<?php
echo "<tr><td>Average</td>";
for($i=0; $i<=$tc-1;$i++)
{
echo "<td>" .round($num[$i],2). "</td>";
}
echo "<tr><td>Max</td>";
$arr_max = array();
foreach($res_arr as $subArray)
{
foreach($subArray as $k=>$v) {
$arr_max[$k][] = $v;
}
}
$max_array = array_map('max', $arr_max);
for($i=0; $i<=$tc-1;$i++)
{
echo "<td>" .$max_array[$i]. "</td>";
}
echo "<tr><td>Min</td>";
$arr_min = array();
foreach($res_arr as $subArray)
{
foreach($subArray as $k=>$v1) {
$arr_min[$k][] = $v1;
}
}
$min_array = array_map('min', $arr_min);
for($g=0; $g<= $tc-1;$g++)
{
echo "<td>" .$min_array[$g]. "</td>";
}
?>
</tbody>
</table>
See inline comments for explanation.
$avArray = array();
$res_arr= array(
0=>array(1,2,3,6,7,8,9,11,33,44,55,66,77,88,16,18),
1=>array(17,52,38,666,79,8,9,15,33,44,55,66,76,88,16,18),
2=>array(17,562,538,7666,579,688,9,15,933,44,55,660,76,808,106,108),
);
/*
foreach ($res_arr as $k=>$subArray){
foreach ($subArray as $id=>$value){
// this causes "Notice: Undefined offset: 0...15" because you can't add to an undeclared value
$avArray[$id] += $value/count($res_arr);
}
}
*/
$res_count=count($res_arr); // declare this outside of the loop for efficiency
foreach ($res_arr as $k=>$subArray){
foreach ($subArray as $id=>$value){
if($k==0){
$avArray[$id]=$value; // declare first round of values
}else{
$avArray[$id]+=$value; // add to existing values
if($k==2){
$avArray[$id]=$avArray[$id]/$res_count; // only divide on the last iteration
}
}
}
}
print_r($avArray);
No matter how you want to present it, you are going to have to loop over the data set more than one. Once to calculate and once to display.
Here is another snippet: (Demo)
$array = [
[1,2,3,6,7,8,9,11,33,44,55,66,77,88,16,18],
[17,52,38,666,79,8,9,15,33,44,55,66,76,88,16,18],
[17,562,538,7666,579,688,9,15,933,44,55,660,76,808,106,108],
];
$count = count($array);
$mins = [];
$maxs = [];
$avgs = [];
foreach ($array as $i => $row) {
foreach ($row as $col => $value) {
$ch = $col + 1;
if (!$i) {
$mins[$ch] = $value;
$maxs[$ch] = $value;
$avgs[$ch] = $value;
} else {
if ($value < $mins[$ch]) {
$mins[$ch] = $value;
}
if ($value > $maxs[$ch]) {
$maxs[$ch] = $value;
}
$avgs[$ch] += $value;
if ($i === $count - 1) {
$avgs[$ch] = number_format($avgs[$ch] / $count, 2);
}
}
}
}
echo '<table border=1>';
printf(
'<tr><th>Channels</th><th>CH%s</th></tr>',
implode('</th><th>CH', array_keys($avgs))
);
printf(
'<tr><th>Average</th><td>%s</td></tr>',
implode('</td><td>', $avgs)
);
printf(
'<tr><th>Max</th><th>%s</td></tr>',
implode('</td><td>', $maxs)
);
printf(
'<tr><th>Min</th><td>%s</td></tr>',
implode('</td><td>', $mins)
);
echo '</table>';

Highlight every other row of a table in a foreach loop and highlight columns depending on value of row

I had a really long description written for my problem, but I've progressed and have managed to get it partially working... I basically want every other row in a table to be a different color - and to highlight certain rows if they meet a condition that I set.
foreach ($data as $row) {
$style = null;
while (($values = fgetcsv($handle, 0, '|')) !== false) {
$comment_lines = $values[6];
$priority = $values[7];
$time_worked = $values[11];
$var_X = strpos($priority, '1');
$var_C1 = strpos($comment_lines, 'CCB');
$var_C2 = strpos($comment_lines, 'CEB');
$var_U = empty($time_worked);
}
if (empty($values[0]) && count($values) === 1) {
continue;
}
if (strlen($var_X)) {
echo '<tr class="gradeX">';
foreach ($values AS $index => $value) {
echo '<td>' . $value . '</td>' ;
}
} else if ($var_C1 !== false) {
echo '<tr class="gradeC">';
foreach ($values AS $index => $value) {
echo '<td>' . $value . '</td>' ;
}
} else if ($var_C2 !== false) {
echo '<tr class="gradeC">';
foreach ($values AS $index => $value) {
echo '<td>' . $value . '</td>' ;
}
} else if ($var_U !== false) {
echo '<tr class="gradeU">';
foreach ($values AS $index => $value) {
echo '<td>' . $value . '</td>' ;
}
} else if ($odd) {
$odd = !$odd;
echo '<tr class="even gradeA">';
foreach ($values AS $index => $value) {
echo '<td>' . $value . '</td>' ;
}
} else {
$odd = !$odd;
echo '<tr class="odd gradeA">';
foreach ($values AS $index => $value) {
echo '<td>' . $value . '</td>' ;
}
}
echo '</tr>';
}
Right now, only the 'every other' is working. I can't get the gradeX, gradeC and gradeU to show anything...
EDIT:
This is the working code, cheers.
while (($values = fgetcsv($handle, 0, '|')) !== false) {
$style = null;
$comment_lines = $values[6];
$priority = $values[7];
$time_worked = $values[11];
$var_X = strpos($priority, '1');
$var_C1 = strpos($comment_lines, 'CCB');
$var_C2 = strpos($comment_lines, 'CEB');
$var_U = empty($time_worked);
if (empty($values[0]) && count($values) === 1) {
continue;
}
if ($var_X !==false) {
echo '<tr class="gradeX">';
} elseif ($var_C1 !== false) {
echo '<tr class="gradeC">';
} elseif ($var_C2 !== false) {
echo '<tr class="gradeC">';
} elseif ($var_U !== false) {
echo '<tr class="gradeU">';
} else {
//nothing
}
foreach ($values as $index => $value) {
echo '<td>' . $value . '</td>';
}
echo '</tr>';
}
In your loop you need to add a counter to identify whether you're currently on an 'even' or an 'odd' iteration, and then add either class 'odd' or 'even' into the as you output it.
There's a related question already on here that covers that here: php: how to add odd/even loop in array
The other parts should be fairly easy by using if statements to check if the relevant data exists or not.
For example, strlen will tell you whether a variable has length or not (to put out 'gradeX'), and strpos will allow you to check if a varibale contains a string (for 'gradeC').
If you can target IE later than IE8 and forget about IE8, you can use CSS3:
tr:nth-child(odd) {
background-color: #EEEEEE;
}
tr:nth-child(even) {
background-color: #FFFFFF;
}

Looping through an array of arrays, changing output on a given line(s)

This is what im using to loop through an array of arrays.
$csvpre = explode("###", $data);
$i = 0;
$bgc = 0;
foreach ( $csvpre AS $key => $value){
$info = explode("%%", $value);
$i++;
if($i == "1"){
echo "<tr bgcolor=#efefef><td></td>";
foreach ( $info as $key => $value ){ echo "<td>$value</td>"; }
echo "</tr>";
} else {
if($bgc=1) { $bgcgo = "bgcolor=\"#b9b9b9\"" ;} else { $bgcgo = "bgcolor=\"#d6d6d6\""; }
echo "<tr $bgcgo><td></td>";
foreach ( $info as $key => $value ){ echo "<td>$value</td>"; }
echo "</tr>";
$bgc++;
}
}
How can i add an if/elseif statement to the last foreach, so that the output changes on a given line of the array.
Say i want <td>$value</td> for all unless specified, but on line 30, i want <textarea>$value</textarea>
You mean like this:
<?php
.......
echo "<tr $bgcgo><td></td>";
$j = 0; //you need a counter
foreach ( $info as $key => $value ) {
$j++;
if ($j != 30) {
echo "<td>$value</td>";
} else {
echo "<textarea>$value</textarea>";
}
}
echo "</tr>";

Categories