Related
Continuing on my previous question.
I have text log file called reject. You can see it here
As you can see there are 4 steps on tab called:
1. Battery level
2. Piezo sound level
3. Left D3 (Ch 3) light intensity
4. Right D2 (Ch 1) light intensity
Now I want to count every row with condition:
Which column(Steps) value is filled then count it.
Example: on row 1, We can see the value 0 (any value) is on step Piezo sound level. Then count it.
So finally I can know how many quantity Reject Process.
Battery level = x quantity
Piezo sound level = x quantity
Left D3 (Ch 3) light intensity = x quantity
Right D2 (Ch 1) light intensity = x quantity
The PHP Code:
$fromDateTime = new DateTime('Wed, Sep 19 2018 08:00:00');
$toDateTime = new DateTime('Wed, Sep 19 2018 19:59:00');
$file = file_get_contents('reject.txt');
$lines = explode("\n",$file);
// counter
$rowsintimespan = 0;
// Do Line-By-Line starting by Line 16 (Array Index 15)
for($i = 15; $i < count($lines); $i++) {
// if the file is "Tue, Sep 18<tab>2018<tab>23:59:53<tab>"
$dateobj = DateTime::createFromFormat("???,?M?d??Y?H:i:s+", $lines[$i]);
// check if date is in your Timespan
if($dateobj < $toDateTime && $dateobj > $fromDateTime) {
$rowsintimespan++; // count if in timespan
}
}
// Debug-Output
echo $rowsintimespan;
UPDATE
I need to read the last column value, Example: if the value of row is on column Left D3 then count it. If the value of row is on column Piezo then count it.
if you're ok with writing down your columns as keys then this should work as you described:
$fromDateTime = new DateTime('Wed, Sep 19 2018 08:00:00');
$toDateTime = new DateTime('Wed, Sep 19 2018 19:59:00');
$file = file_get_contents('Reject.txt');
$lines = explode("\n", $file);
// counter
$rowsintimespan = 0;
// keys should correspond to columns
$keys = [
'date',
'time',
'battery',
'piezo',
'leftD3',
'rightD2'
];
$values = array_fill(0, count($keys), 0);
$values = array_combine($keys, $values);
// Do Line-By-Line starting by Line 16 (Array Index 15)
for ($i = 11; $i < count($lines); $i++) {
// if the file is "Tue, Sep 18<tab>2018<tab>23:59:53<tab>"
$dateobj = DateTime::createFromFormat("???,?M?d??Y?H:i:s+", $lines[$i]);
// check if date is in your Timespan
if ($dateobj < $toDateTime && $dateobj > $fromDateTime) {
$rowsintimespan++; // count if in timespan
// get line elements
$lineContent = explode("\t", $lines[$i]);
// loop through line elements and count them
$x = 0;
for ($j = 0; $j < count($keys); $j++) {
if (!isset($lineContent[$j])) {
continue;
}
// remember position of last not empty column
if (trim($lineContent[$j]) != '') {
$x = $j;
}
}
if ($x > 0) {
$values[$keys[$x]]++;
}
}
}
// Debug-Output
echo $rowsintimespan;
// Output every column
echo '<pre>';
print_r($values);
This will print out:
Array
(
[date] => 0
[time] => 0
[battery] => 4
[piezo] => 31
[leftD3] => 17
[rightD2] => 1
)
Just split your row by your tabs and check for !empty();
//Set Time-Span
$fromDateTime = new DateTime('Wed, Sep 19 2018 00:00:00');
$toDateTime = new DateTime('Wed, Sep 19 2018 17:00:00');
// Load File
$file = file_get_contents('Reject.txt');
// Split by lines
$lines = explode("\n",$file);
// counter
$rowsintimespan = 0;
$rowswithbattery = 0;
// Do Line-By-Line starting by Line 16 (Array Index 15)
for($i = 15; $i < count($lines); $i++) {
// if the file is "Tue,<space>Sep<space>18<space><space>2018<tab>23:59:53<tab>"
$dateobj = DateTime::createFromFormat("???, M d?Y?H:i:s+", $lines[$i]);
// check if date is in your Timespan
if($dateobj < $toDateTime && $dateobj > $fromDateTime) {
$rowsintimespan++; // count if in timespan
$cols = explode("\t",$lines[$i]);
// 0 = Date, 1 = Time, 2 = Battery Level, 3 = Piezo, 4 = left, 5 = Right
// Count Battery-Values
if (!empty($cols[2])) {
$rowswithbattery++;
}
}
}
// Debug-Output
echo 'In Timespan: '.$rowsintimespan."\n";
echo 'Rows With Battery: '.$rowswithbattery
Produces:
In Timespan: 84
Rows With Battery: 84
Full Example with all your columns: https://ideone.com/VAQH7h
Also you could iterate over every header and create a neat array as I showed in https://ideone.com/YUU1jP
// Split by lines
$lines = explode("\n", $file);
$header = explode("\t", $lines[9]);
// counter
$rowsintimespan = 0;
$counter = Array();
// Create an entry for every header and trim it to lose additional whitespaces
foreach($header as $index => $head){
$counter[rtrim($head)] = 0;
}
// Do Line-By-Line starting by Line 16 (Array Index 15)
for($i = 11; $i < count($lines); $i++) {
// the file is "Tue,<space>Sep<space>18<space><space>2018<tab>23:59:53<tab>"
$dateobj = DateTime::createFromFormat("???, M d Y?H:i:s+", $lines[$i]);
// check if date is in your Timespan
if($dateobj < $toDateTime && $dateobj > $fromDateTime) {
$rowsintimespan++; // count if in timespan
$cols = explode("\t",$lines[$i]);
// 0 = Date, 1 = Time, 2 = Battery Level, 3 = Piezo, 4 = left, 5 = Right
// Count Battery-Values
foreach($header as $index => $head){
// For every header check if col is empty
$counter[rtrim($head)] += empty($cols[$index]) ? 0 : 1;
}
}
}
// Debug-Output
echo 'In Timespan: '.$rowsintimespan."\n";
var_dump($counter);
Update to match the updated question:
Then just do some simple math.
Theory: if you have 80 set columns with battery, and 20 with set piezo, you can substract the 20 piezo counter from your 80 battery counter and then you know how many last battery-columns you have and how many last piezo columns.
Thus:
$lastwithright = $rowswithright;
$lastwithleft = $rowswithleft - $rowswithright;
$lastwithpiezo = $rowswithpiezo - $rowswithleft;
$lastwithbattery = $rowswithbattery - $rowswithpiezo;
I want to have an array which is always ascending without a gap between days, months or years. So, at the end I want to have something like this for example 2012, 2013, 2014, 2015, 2016.
Example arrays:
$data = [2012, 2013, 2015, 2017]
$anzeige = [1, 5, 8, 3]
Want I want to have at the end:
$data = [2012, 2013, 2014, 2015, 2016, 2017]
$anzeige = [1, 5, 0, 8, 0, 3]
But sometimes there are no data avaiveble for some days, months or years. So, I have a gap. I want to close this gap and add the following day, month or year to the array and it should remain ascending.
This is my code so far:
private function fixDates($daten, $anzahl){
$tmpArrayDaten = array();
$tmpArrayAnzahl = array();
$this->logger->lwrite("Fix Data");
for ($i=0; $i < sizeof($daten) - 1 ; $i++) {
if(($i + 1) == sizeof($daten)){
return array(array("daten" => $daten), array("anzahl" => $anzahl));
}
if(!(($daten[$i] + 1) == ($daten[$i + 1]))){
$this->logger->lwrite(($daten[$i] + 1) . " != " . ($daten[$i + 1]));
for($j = 0; $j < $i; $j++){
$tmpArrayDaten[] = $daten[$j];
$tmpArrayAnzahl[] = $anzahl[$j];
}
$tmpArrayDaten[] = $daten[$i] + 1;
$tmpArrayAnzahl[] = 0;
for($j = $i; $j < (sizeof($daten) + 1); $j++){
$tmpArrayDaten[] = $daten[$j];
$tmpArrayAnzahl[] = $anzahl[$j];
}
$this->logger->lwrite(var_export($tmpArrayDaten));
$this->logger->lwrite(var_export($tmpArrayAnzahl));
$this->fixDates($tmpArrayDaten, $tmpArrayAnzahl);
}
}
return array(array("daten" => $daten), array("anzahl" => $anzahl));
}
The $anzahl array contains the value for the day, month or year at the same index in the $daten array. And no, I do not want to have them in one array because I am going to create one array at the end to send it via json_encode() to JavaScript.
However, I cannot find my failure in my code... It never stops. It doesn't stop to add "placeholder" if there is a gap...
Do you may have an idea how to fix that?
Kind regards
$data = [2012, 2013, 2016, 2017, 2020];
$anzeige = [1, 5, 8, 3, 10];
list($new_data, $new_clicks) = fillGaps($data, $anzeige);
print_r($new_data);
print_r($new_clicks);
function fillGaps($data, $clicks) {
// assume the first element is right
$fixed_data = array($data[0]);
$fixed_clicks = array($clicks[0]);
for ($i = 1; $i < count($data); $i++) {
// if there is a gap, fill it (add 0s to corresponding array)
while (end($fixed_data)+1 != $data[$i]) {
$fixed_data[] = end($fixed_data) + 1;
$fixed_clicks[] = 0;
}
// add the data which exists after gap
$fixed_data[] = $data[$i];
$fixed_clicks[] = $clicks[$i];
}
return array($fixed_data, $fixed_clicks);
}
I have this json string that it's stored as text in a mysql database (I have that in a "cronograma" field).
This is what $row['cronograma'] outputs:
{"fecha":["02 enero","05 enero","20 enero","22 enero","25
enero"],"bolilla":["22","26","15","28","33"],"docente":["Juan","Pedro","Lidia","Maxima","Luis"]}
And I want to extract the information from it, and presented it in screen.
This is how I extract the information with json_decode() and loop through it with a foreach:
$cronograma = json_decode($row['cronograma'], true);
$cant = count($cronograma['fecha']);
echo $cant.'<br>'; //this outputs 5
$i = 0;
foreach ($cronograma as $key => $value) {
echo $i;
$fecha = $cronograma['fecha'][$i];
$bolilla = $cronograma['bolilla'][$i];
$docente = $cronograma['docente'][$i];
echo "<b>Fecha:</b> $fecha <b>Bolilla:</b> $bolilla <b>Docente:</b> $docente<br>";
if ($i < $cant) $i++;
}
Now, my problem is that it won't output the five items in the array, but just three, and I don't understand why. Even if I change ($i < $cant) to ($i < 5), it still outputs only 3.
This is the output:
0Fecha: 02 enero Bolilla: 22 Docente: Juan
1Fecha: 05 enero Bolilla: 26 Docente: Pedro
2Fecha: 20 enero Bolilla: 15 Docente: Lidia
And this is what it should be:
0Fecha: 02 enero Bolilla: 22 Docente: Juan
1Fecha: 05 enero Bolilla: 26 Docente: Pedro
2Fecha: 20 enero Bolilla: 15 Docente: Lidia
3Fecha: 22 enero Bolilla: 28 Docente: Maxima
4Fecha: 25 enero Bolilla: 33 Docente: Luis
What am I missing?
i think your foreach loop causing the problem...you are using 'cronograma' as your foreach loop array which has only three elements 'fecha' ,'bolilla' & 'docente' so the loop runs only thrice no matter what value you set for variable i against 'cant'
$x='{"fecha":["02 enero","05 enero","20 enero","22 enero","25 enero"],"bolilla":["22","26","15","28","33"],"docente":["Juan","Pedro","Lidia","Maxima","Luis"]}';
$cronograma = json_decode($x, true);
$cant = count($cronograma['fecha']);
echo $cant.'<br>'; //this outputs 5
$i = 0;
for($i=0;$i<$cant;$i++) {
echo $i;
$fecha = $cronograma['fecha'][$i];
$bolilla = $cronograma['bolilla'][$i];
$docente = $cronograma['docente'][$i];
echo "<b>Fecha:</b> $fecha <b>Bolilla:</b> $bolilla <b>Docente:</b> $docente<br>";
}
You just need a while loop to go through $cant
<?php
$cronograma = '{"fecha":["02 enero","05 enero","20 enero","22 enero","25 enero"],"bolilla":["22","26","15","28","33"],"docente":["Juan","Pedro","Lidia","Maxima","Luis"]}';
$cronograma = json_decode($cronograma, true);
$cant = count($cronograma['fecha']);
echo $cant.'<br>'; //this outputs 5
$i = 0;
while ($i < $cant){
$fecha = $cronograma['fecha'][$i];
$bolilla = $cronograma['bolilla'][$i];
$docente = $cronograma['docente'][$i];
echo "<b>Fecha:</b> $fecha <b>Bolilla:</b> $bolilla <b>Docente:</b> $docente<br>";
$i++;
}
Because $cronograma contains 3 items; fecha, bolilla & docente, so I recommend changing your loop like:
$cronograma = json_decode($row['cronograma'], true);
$cant = count($cronograma['fecha']);
echo $cant.'<br>'; //this outputs 5
for ($i = 0; $i < $cant; $i++) {
echo $i;
$fecha = $cronograma['fecha'][$i];
$bolilla = $cronograma['bolilla'][$i];
$docente = $cronograma['docente'][$i];
echo "<b>Fecha:</b> $fecha <b>Bolilla:</b> $bolilla <b>Docente:</b> $docente<br>";
}
I don't know PHP very well, so please bear with me.
My client has a database with information and one of the fields is ff_date_time in the format "Tue Oct 5 14:43:10 2010". There are a lot of entries in here and I need to display a list of just the days that have entries: ie, Tue Oct 5, 2010Thurs Oct 7, 2010 and so on. There may be hundreds of entries on a certain day, so obviously when I pull in dates from the db I need to go through and extract the right data and filter it. Here's what I have so far:
$query = "SELECT ff_date_time FROM booth_submit";
$query_result = mysql_query($query);
$datetimes = array();
$dates = array();
while ($row = mysql_fetch_array($query_result)) {
$datetimes[] = $row['ff_date_time'];
}
for ($i = 0; $i < sizeOf($datetimes); $i++) {
$temp = explode(" ", $datetimes[$i]);
$dates[] = ($temp[0]." ".$temp[1]." ".$temp[2]." ".$temp[4]); # Breaks date_time into 'Mon Oct 5 2010' format
}
$dates = array_unique($dates);
for ($i = 0; $i < sizeOf($dates); $i++) {
echo(''.$dates[$i].'<br />');
}
I'm doing a similar thing for two others fields that work fine, but for some reason, this always yields a $dates array that is the right length (ie: 4 unique dates, array is size 4), but only the first $dates element has any info. The output looks like this:
Mon Oct 3 2010<br />
<br />
<br />
<br />
When I don't use array_unique and just test values to check if everything is getting loaded and parsed correctly, the array is just as it should be ("Mon Oct 3 2010","Mon Oct 3 2010","Mon Oct 3 2010","Mon Oct 4 2010","Mon Oct 5 2010","Mon Oct 5 2010","Mon Oct 6 2010").
Any clues what's going wrong here?
array_unique preserves the keys so your resulting array has elements [0], [4] and [6].
I suggest using
foreach ($dates as $date) {
echo(''.$date.'<br />');
}
Assign the unique array to another array variable. And use foreach.
$newarr = array();
$newarr = array_unique($dates);
foreach ($newarr as $date) {
echo(''.$date.'<br />' . "\n");
}
I would rather recommend you another approach. Using the built-in datetime functions.
$all_dates = array();
foreach($datetimes as $date) {
$all_dates[] = date('D M j Y', strtotime($date));
}
$unique = array_unique($all_dates);
How about instead of treating the symptom, you remove the cause.
Add GROUP BY ff_date_time to the end of your query, or wrap DISTINCT() around ff_date_time in the select. Then you'll only get unique dates in your sql result.
edit: ok, assuming that ff_date_time is actually a datetime field, then in order to ignore time of day, make that GROUP BY DATE(ff_date_time) which will use only the day part and not the time part. If it's not a datetime field, and just a string, you will have to do substring functions, or use someone else's answer.
What is the output of var_dump($dates) after you used array_unique?
Try foreach instead of a for loop:
foreach($dates as $date) {
echo(''.$date.'<br />');
}
This question already has answers here:
How to pad single-digit numbers with a leading 0
(7 answers)
Closed 11 months ago.
for ($number = 1; $number <= 16; $number++) {
echo $number . "\n";
}
This code outputs:
1
2
3
...
16
How can I get PHP to output the numbers preceded by zeros?
01
02
03
...
16
You could use sprintf to format your number to a string, or printf to format it and display the string immediatly.
You'd have to specify a format such as this one, I'd say : %02d :
padding specifier = 0
width specifier = 2
integer = d
(Even if you have what you want here, you should read the manual page of sprintf : there are a lot of possibilities, depending on the kind of data you are using, and the kind of output formating you want)
And, as a demo, if temp.php contains this portion of code :
<?php
for ($number = 1; $number <= 16; $number++) {
printf("%02d\n", $number);
}
Calling it will give you :
C:\dev\tests\temp>php temp.php
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
You can use str_pad().
str_pad — Pad a string to a certain length with another string
This functions returns the input string padded on the left, the right, or both sides to the specified padding length. If the optional argument pad_string is not supplied, the input is padded with spaces, otherwise it is padded with characters from pad_string up to the limit.
The old-fashioned way:
$str = sprintf("%02.2d", $number);
or use
printf("%02.2d\n", $number);
to print it immediately.
for ($number = 1; $number <= 16; $number++) {
echo sprintf("%02d", $number) . "<br>";
}
if($number < 10) echo '0' . $number;
I know there are a lot better answers than this here, but I though't I'd leave it to show there's more than one way to skin a cat...
Quick method:
<?php
for ($number = 1; $number <= 16; $number++)
{
if($number < 10)
echo "0".$number."\n";
else
echo $number."\n";
}
?>
Lets keep it simple.
Use str_pad
echo str_pad(1, 6 , "0");
produces 000006
echo ($number < 10) ? (0 . $number) : $number;
<?php
for ($number = 1; $number <= 16; $number++)
{
if($number<10)
echo '0';
echo $number . "<br>";
}
?>