php - converting badly formatted txt to csv - php

i have a badly formatted text file which i would like to convert to csv.
Here's an example:
100910 NA/1-2013-99636 VIA DEI PESCATORI 2/A LODI APR 8 2013 4:24PM DANNEGGIATO -10% 200 2700 0 0 NO
148013 NA/1-2014-146194 CAVALLOTTI SNC LODI GEN 3 2014 3:37PM DANNEGGIATO -10% 0 0 2 0 NO
160032 NA/1-2014-158129 PAOLO GORINI SNC LODI MAG 6 2014 11:51AM DANNEGGIATO -10% 2 0 2 0 NO
54900 NA/1-2014-158070 STRADA VECCHIA CREMONESE SNC LODI MAG 6 2014 9:53AM DANNEGGIATO +10% 10 0 10 0 NO
100910 NA/1-2013-99636 VIA DEI PESCATORI 2/A LODI APR 8 2013 4:24PM DANNEGGIATO -10% 200 2700 0 0 NO
147959 NA/1-2014-146140 DOSSENA SNC LODI GEN 3 2014 10:45AM DANNEGGIATO -10% 200 0 200 0 NO
That is roughly in this form :
[number] [id] [awfully formatted street] ['LODI'] [timestamp] [damaged or not] [percentage] [squaremeters] [squaremeters] [squaremeters] [squaremeters] [asbest-crumbled or not]
My problem is how to extract the 3rd part, [awfully formatted street].
Basically it's the string after [id] preceding the string ['LODI'] (but ['LODI'] must be just before [timestamp] )
Should i explode() each line by spaces and then traversing the array backwards, overtake [timestamp], overtake ['LODI'] and joining the values before array[id], i.e array [1]? Or is there a smarter (elegant) way to do this, perhaps with preg_match()?
Thanks for any hint!

<?php
// read file line by line
$line = '148013 NA/1-2014-146194 CAVALLOTTI SNC LODI GEN 3 2014 3:37PM DANNEGGIATO -10% 0 0 2 0 NO';
//start by seperating the string on LODI
$lodi_split = explode('LODI', $line);
// Now split the first occ into an array on space
$bits = explode(' ', $lodi_split[0]);
$address = '';
// start reading occurance from occ 2 to loose the first 2 fields
for ($i=2; $i < count($bits); $i++ ) {
$address .= $bits[$i] . ' ';
}
echo $address . PHP_EOL;
Result is
CAVALLOTTI SNC

This should work to extract the address from a row.
<?php
$row = "100910 NA/1-2013-99636 VIA DEI PESCATORI 2/A LODI APR 8 2013 4:24PM DANNEGGIATO -10% 200 2700 0 0 NO";
$row_array = preg_split('/\s+/', $row);
array_shift($row_array);
array_shift($row_array);
for($i=0; $i<12; $i++){
array_pop($row_array);
}
$address = implode(" ", $row_array);
?>

I think explode won't do here. I propose using regexp. For Instance, If you read your .txt file as one string(where data strings are separated with \n):
$f = fopen($fname="file.txt", "rt");
$str = fread($f, filesize($fname)));
fclose($f);
Then use preg_match_all() like this:
$re = "/^(\\d+)\\s*(.*)(LODI)\\s*(.+(?:AM|PM))\\s*(\\w+)\\s+(-?\\d{1,3}%)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\w+)$/m";
preg_match_all($re, $str, $matches,PREG_SET_ORDER );
echo "<pre>\n";
print_r($matches);
echo "</pre>\n";
The output would look like this:
Array
(
[0] => Array
(
[0] => 100910 NA/1-2013-99636 VIA DEI PESCATORI 2/A LODI APR 8 2013 4:24PM DANNEGGIATO -10% 200 2700 0 0 NO
[1] => 100910
[2] => NA/1-2013-99636 VIA DEI PESCATORI 2/A
[3] => LODI
[4] => APR 8 2013 4:24PM
[5] => DANNEGGIATO
[6] => -10%
[7] => 200
[8] => 2700
[9] => 0
[10] => 0
[11] => NO
)
[1] => Array
(
[0] => 148013 NA/1-2014-146194 CAVALLOTTI SNC LODI GEN 3 2014 3:37PM DANNEGGIATO -10% 0 0 2 0 NO
[1] => 148013
[2] => NA/1-2014-146194 CAVALLOTTI SNC
[3] => LODI
[4] => GEN 3 2014 3:37PM
[5] => DANNEGGIATO
[6] => -10%
[7] => 0
[8] => 0
[9] => 2
[10] => 0
[11] => NO
)
..........// And so on
I used the text that you provided above in this example. So in the output you recieve your data formated as list of arrays. So you can do whatever you want with it. $matches[$i][0] - will store the whole match so just skip it and use $matches[$i][1]....$matches[$i][11] as your data.

Related

Multi dimensional php array not working

Hi I'm trying to create a multi dimensional array but having problems. I have a multi dimensional array that I'm trying to push other arrays onto. The arrays are created and pushed within an array.
$initialChild = $selectorDetailsArray[0];
$selectorDetailsMultiDimArray = array();
$multiDimHoldArray = array();
for($r=0;$r<count($selectorDetailsArray);$r+=3){
echo "Test vars are ".$selectorDetailsArray[$r]." : ".$initialChild."<br> ";
if(intval($selectorDetailsArray[$r]) == intval($initialChild)){
echo"<br> r is ".$r."<br>";
array_push($multiDimHoldArray,$selectorDetailsArray[$r+1],$selectorDetailsArray[$r+2]);
echo"<br> values are ".$selectorDetailsArray[$r+1]." ".$selectorDetailsArray[$r+2]."<br>";
print "<pre>";
print_r($multiDimHoldArray);
print "</pre>";
}else{
array_push($selectorDetailsMultiDimArray,$multiDimHoldArray);
$multiDimHoldArray = array();
echo "initial child is ".$initialChild."<br>";
$initialChild = $selectorDetailsArray[$r];
echo "initial child after change is ".$initialChild."<br>";
}
}
print "<pre>";
print_r($selectorDetailsMultiDimArray);
print "</pre>";
exit;
output is like this
Array
(
[0] => 65
[1] => 1
[2] => 0
[3] => 65
[4] => 29
[5] => 64
[6] => 66
[7] => 1
[8] => 69
[9] => 66
[10] => 29
[11] => 65
)
Test vars are 65 : 65
r is 0
values are 1 0
Array
(
[0] => 1
[1] => 0
)
Test vars are 65 : 65
r is 3
values are 29 64
Array
(
[0] => 1
[1] => 0
[2] => 29
[3] => 64
)
Test vars are 66 : 65
initial child is 65
initial child after change is 66
Test vars are 66 : 66
r is 9
values are 29 65
Array
(
[0] => 29
[1] => 65
)
Array
(
[0] => Array
(
[0] => 1
[1] => 0
[2] => 29
[3] => 64
)
)
I can't get it to push the second array - I must be missing something?
I've tried everything I can think of but can't figure out why the second array (that's been created) isn't pushed onto the multi dimensional array.
Any help would be great
Not sure what the overall purpose of the code is for "exactly" but I do understand the results you were trying to get, and I also understand why it was not working. I have commented my code so you should be able to see what it is doing. I created an array in the code to start with, but I presume it would work with whatever array you are getting even though you are not showing how it was generated.
$selectorDetailsArray = Array(65,1,0,65,29,64,66,1,69,66,29,65);
$initialChild = $selectorDetailsArray[0];
$selectorDetailsMultiDimArray = array();
$multiDimHoldArray = array();
$loopstrings = array(" :: 1st loop :: "," :: 2nd loop :: "," :: 3rd loop :: "," :: 4th loop :: ");
$loop = 0;
$dim = 0;
for($r=0;$r<count($selectorDetailsArray);$r+=3){
echo "<br>START".$loopstrings[$loop]."<br>";
echo "Test vars are ".$selectorDetailsArray[$r]." : ".$initialChild."<br> ";
if(intval($selectorDetailsArray[$r]) == intval($initialChild)){
echo"<br> r is ".$r."<br>";
array_push($multiDimHoldArray,$selectorDetailsArray[$r+1],$selectorDetailsArray[$r+2]);
echo"<br> values are ".$selectorDetailsArray[$r+1]." ".$selectorDetailsArray[$r+2]."<br>";
}else{
array_push($selectorDetailsMultiDimArray,$multiDimHoldArray);
$multiDimHoldArray = array();
// This needs to be here because the "if" is not run during this loop...
array_push($multiDimHoldArray,$selectorDetailsArray[$r+1],$selectorDetailsArray[$r+2]);
echo "initial child is ".$initialChild."<br>";
$initialChild = $selectorDetailsArray[$r];
echo "initial child after change is ".$initialChild." -- ($ r = $r)<br>";
}
echo "<br>END".$loopstrings[$loop++]."<br>";
}
// We push one last time since it successfully pushed twice more in the "if" but never ran the "else" a final time...
array_push($selectorDetailsMultiDimArray,$multiDimHoldArray);
echo "<br>";
echo "<br>BEGIN OUTPUT<br>";
print "<pre>";
print_r($selectorDetailsArray);
print_r($multiDimHoldArray);
print_r($selectorDetailsMultiDimArray);
print "</pre>";
This is the output that my code generates. I have added a few lines to make it readable, and also output all of the arrays at the end:
START :: 1st loop ::
Test vars are 65 : 65
r is 0
values are 1 0
END :: 1st loop ::
START :: 2nd loop ::
Test vars are 65 : 65
r is 3
values are 29 64
END :: 2nd loop ::
START :: 3rd loop ::
Test vars are 66 : 65
initial child is 65
initial child after change is 66 -- ($ r = 6)
END :: 3rd loop ::
START :: 4th loop ::
Test vars are 66 : 66
r is 9
values are 29 65
END :: 4th loop ::
BEGIN OUTPUT
Array
(
[0] => 65
[1] => 1
[2] => 0
[3] => 65
[4] => 29
[5] => 64
[6] => 66
[7] => 1
[8] => 69
[9] => 66
[10] => 29
[11] => 65
)
Array
(
[0] => 1
[1] => 69
[2] => 29
[3] => 65
)
Array
(
[0] => Array
(
[0] => 1
[1] => 0
[2] => 29
[3] => 64
)
[1] => Array
(
[0] => 1
[1] => 69
[2] => 29
[3] => 65
)
)

Increment a variable with numeric and uppercase letter

Can you tell me how I can increment a variable in PHP from 00 to ZZ ?
With A5, 8R, GG...
I tried this but it's just for letter :
for($i="AA"; $i<="ZZ" AND strlen($i)<=2; $i++)
Thank you
i created a little snippet that should demonstrate how you can use range($start,$end) to create what you are looking for
<?php
//create an array with all values from 0-9 and A-Z
$range = array_merge(range("0","9"),range("A","Z"));
//create counter-aray
$counter = array();
//loop through the range
foreach($range as $value1){
foreach($range as $value2){
$counter[] = $value1.$value2;
}
}
//show the counter
print_r($counter);
?>
result:
Array
(
[0] => 00
[1] => 01
[2] => 02
[3] => 03
[4] => 04
[5] => 05
[6] => 06
[7] => 07
[8] => 08
[9] => 09
[10] => 0A
[11] => 0B
[12] => 0C
[13] => 0D
[14] => 0E
[15] => 0F
[16] => 0G
[17] => 0H
[18] => 0I
[19] => 0J
[20] => 0K
[21] => 0L
.....many more values follow here
)
feel free to ask questions if you need further explaination
It actually sounds as if you are trying to add numbers in base 36. Since PHP can convert between bases, you could add the numbers in base 10 then convert into base 36.
for($i = 0; $i <= base_convert("zz", 36, 10); $i++) {
echo(str_pad(strtoupper(base_convert($i, 10, 36)), 2, "0", STR_PAD_LEFT) . PHP_EOL);
}
$i is an integer in base 10 that will loop from 0 to 1295. (zz in base 10.)
base_convert converts $i from base 10 to base 36.
strtoupper converts the resulting string to uppercase so you get AA instead of aa.
str_pad will add leading 0s to convert values such as 0 to 00.

Transpose query result set [duplicate]

This question already has answers here:
Transposing multidimensional arrays in PHP
(12 answers)
Chunk and transpose a flat array into rows with a specific number of columns
(3 answers)
Closed 5 months ago.
So I have a database with players names and their skill level.
It looks like this:
Id | Name | Level
1 | Peter | 24
2 | Andy | 23
...
24 | John | 1
The first player in the list with the highest level is the strongest one, and the last is the weakest.
I need to sort them in groups with 4 players, so if I have 24 people there will be 6 groups.
The way I need to sort it I call "zig-zag".
It goes like this:
Ag Bg Cg Dg Eg Fg
01 02 03 04 05 06
12 11 10 09 08 07
13 14 15 16 17 18
24 23 22 21 20 19
So the A group will consist of players: 1, 12, 13, 24.
B group of players: 2, 11, 14, 23.
C group of players: 3, 10, 15, 22 and so on.
It's easy to do it by hand, but how I could automate this sort with PHP language?
The groups should be array list (I think so) which could I easily put to the group tables in database.
The idea would be to:
Sort your starting data (or preferably, start with it sorted).
Split it into chunks, basically one per each of your rows.
Reverse the order of every other chunk.
Flip the matrix so you've got your groups - one per column instead of one per row.
Example:
// Basic sample data.
$players = range(1, 24);
// Sort them ascending if you need to.
sort($players);
// Make a matrix. 2d array with a column per group.
$matrix = array_chunk($players, ceil(count($players)/4));
// Reverse every other row.
for ($i = 0; $i < count($matrix); $i++) {
if ($i % 2) {
$matrix[$i] = array_reverse($matrix[$i]);
}
}
// Flip the matrix.
$groups = array_map(null, ...$matrix); // PHP 5.6 with the fancy splat operator.
//$groups = call_user_func_array('array_map', array_merge([null], $matrix)); // PHP < 5.6 - less fancy.
// The result is...
print_r($groups);
Output:
Array
(
[0] => Array
(
[0] => 1
[1] => 12
[2] => 13
[3] => 24
)
[1] => Array
(
[0] => 2
[1] => 11
[2] => 14
[3] => 23
)
[2] => Array
(
[0] => 3
[1] => 10
[2] => 15
[3] => 22
)
[3] => Array
(
[0] => 4
[1] => 9
[2] => 16
[3] => 21
)
[4] => Array
(
[0] => 5
[1] => 8
[2] => 17
[3] => 20
)
[5] => Array
(
[0] => 6
[1] => 7
[2] => 18
[3] => 19
)
)

Changing an array to a json with json_encode

I have this array:
Array
(
[1] => 20130701 4 4 3060 1
[2] => 20130702 270 757 13812810 4
[3] => 20130703 5 123 3894971 2
[4] => 20130704 290 478 5119617 1
[5] => 20130705 88 98 189791 2
[6] => 20130708 9 73 564627 1
[7] => 20130722 6102 11992 41974701 1
[8] => 20130723 6397 11021 40522224 1
[9] => 20130725 4644 9336 49167728 2
[10] => 20130726 4891 10157 33516844 3
[11] => 20130727 123 319 2538226 3
[12] => 20130728 451 801 1078705 2
[13] => 20130729 13609 30407 95551827 5
[14] => 20130730 6354 17550 272794650 158
[15] => 20130731 6270 18456 269468599 174
)
I'm trying to change the output in order to show it in a chart, do i change it into a json:
foreach ($day as $key => $value) {
$value = explode(" ", $value) ;
$day[$key] = $value ;
$charts[] = array(substr($value[0],0,4).'-'.substr($value[0],4,2).'-'.substr($value[0],6,2),$value[4]) ;
}
$charts = json_encode($charts, JSON_NUMERIC_CHECK) ;
But it displays me this :
[["2013-07-01","1\r"],["2013-07-02","4\r"],["2013-07-03","2\r"],["2013-07-04","1\r"],["2013-07-05","2\r"],["2013-07-08","1\r"],["2013-07-22","1\r"],["2013-07-23","1\r"],["2013-07-25","2\r"],["2013-07-26","3\r"],["2013-07-27","3\r"],["2013-07-28","2\r"],["2013-07-29","5\r"],["2013-07-30","158\r"],["2013-07-31","174\r"]]
why \r does show? any way I can prevent this ?
try
$charts[] = array(substr($value[0],0,4).'-'.substr($value[0],4,2).'-'.substr($value[0],6,2),substr($value[4],0, -1)) ;
You have return characters at the end of your array
[3] => 20130703 5 123 3894971 2\r
They are not visible because \n = new line \r returns the pointer to the beginning of the line.
Your best bet is to use trim() on every element:
foreach ($day as $key => $value) {
$value = explode(" ", trim($value));
$day[$key] = trim($value) ;
$charts[] = array(trim(substr($value[0],0,4).'-'.substr($value[0],4,2).'-'.substr($value[0],6,2),$value[4])) ;
}
It's even better on numbers to use intval(), which ensures datatype to be integer and removes blankspaces, returns, ... too.

Insert into array by spaces

I have this TXT file, which each line I would to insert into array, like this:
Array ( [0] => [1] => 8100 [2] => 623 [3] => 09:04 [4] => AM [5] => 00:26 [6] => L [7] => S-ED [8] => 768 [9] => #4506856439 [10] => 00:01 [11] => )
CO USER TIME DURATION TYPE ACCOUNT_CODE CALLED_NUM RING_TIME
8100 623 09:04 AM 00:26 L S-E 250821613987
8021 8816 09:06 AM 00:20 I S-E D 768 #4506856439 00:01
8020 09:06 AM I N D 603 #45424044499 00:30
8011 09:07 AM 00:11 I S-E D 727 #7546355292 00:02
" 8817 00:11
" 00:02 H
8100 623 09:07 AM 00:01 L S-E 5542204034
8007 8818 09:08 AM 00:13 I S-E D 618 #45269021726 00:01
8013 8811 09:09 AM 00:01 I S-E D 770 #436217227 00:01
8014 09:10 AM 00:16 I S-E D 652 #4523859922 00:01
I'd like to insert it into an array with all parameters, even if empty,
but I can't get it work.
I tried this:
$fh = fopen('captures/131210.txt','r');
while ($line = fgets($fh)) {
$tempexp = preg_split('/\s+/', $line);
print_r($tempexp);
echo "<br />";
}
fclose($fh)
But it gives out weird outputs for some values, like this:
Array ( [0] => [1] => " [2] => 8812 [3] => 00:16 [4] => )
Help would be much appreciated!
If the layout of your text file is purely based on spaces you can used the exact columns to extract the data. Since the columns are not of equal width you cannot simply write it in one loop.
Use the substr function to get part of the line (first number is index, second number is length to read)
$fh = fopen('captures/131210.txt','r');
while ($line = fgets($fh)) {
$co = substr($line, 0, 7);
$user = substr($line, 7, 6);
... etc ...
echo "<br />";
}
fclose($fh)
You might need to parse the separate parts further down dependent on the content and what you want to do with it - parse as integer, date, time etc.

Categories