So I have a huge file of names that has to be split into more columns for excel.
So I am using PHP to parse this, so here is part of the example:
Dr. Johnny Apple Seed
Ms. A. P. Oranges
Mrs. Purple Cup
Essentially, I want to put this into an array. I was using fopen, fget, and explode. The problem is, if I use explode, some of the arrays would not have consistent elements. For example, the first one would have a total of 4 (Dr, Johnny, Apple, Seed), the third would have only three. How would I add a fourth empty element between purple and cup? or is there a better way?
This is my code:
$fp = fopen($filename,"r");
if ($fp) {
while (!feof($fp)) {
$data = fgets($fp, filesize($filename));
$contents[] = explode(" ", $data) .
}
}
fclose($fp);
echo "<pre>";
var_dump($contents);
echo "</pre>";
Desired Output:
array(4) {
[0]=>
string(4) "Mrs."
[1]=>
string(4) "Purple"
[2]=>
string(1) " "
[3]=>
string(8) "Cup"
array(4) {
[0]=>
string(3) "Dr."
[1]=>
string(6) "Johnny"
[2]=>
string(5) "Apple"
[3]=>
string(4) "Seed"
Try this (haven't tested but should work):
// Define the clean array
$clean_array = array();
$fp = fopen($filename,"r");
if ($fp) {
while (!feof($fp)) {
$data = fgets($fp, filesize($filename));
// use trim() on $data to avoid empty elements
$contents = explode(" ", trim($data));
if (count($contents) == '3') {
// Copy last element to new last element
$contents[] = $contents[2];
// Clear the old last element
$contents[2] = ' ';
}
$clean_array[] = $contents;
}
}
fclose($fp);
echo '<pre>';
print_r($clean_array);
echo '</pre>';
Hope this helps.
This should work:
<?php
$new_array = array();
$fp = fopen($filename, "r");
if ($fp) {
while (!feof($fp)) {
$data = fgets($fp, filesize($filename));
$contents[] = explode(" ", $data);
}
}
foreach ($contents as $content) {
if (count($content) != 4) {
$content[3] = $content[2];
$content[2] = " ";
$new_array[] = $content;
}
else {
$new_array[] = $content;
}
}
fclose($fp);
echo "<pre>";
var_dump($new_array);
echo "</pre>";
?>
If they are newlines, you can just use "\n" as the $needle
I used array_splice, here is my solution:
<?php
$filename = "excel-names.txt";
$fp = fopen($filename,"r");
if ($fp) {
while (!feof($fp)) {
$data = fgets($fp, filesize($filename));
$contents[] = explode(" ", $data, 4);
}
}
fclose($fp);
foreach( $contents as $a) {
$arrayCount = count($a);
if( $arrayCount == 3 ) {
array_splice($a, 2, 0, " ");
}
if( $arrayCount == 2 ) {
array_splice($a, 0, 0, " ");
array_splice($a, 2, 0, " ");
}
}
?>
Related
I have an array with two string values, but cannot use one of them. If I use
var_dump($array[0]);
it's result is
array(2) { ["id"]=> string(2) "01" ["name"]=> string(10) "Aquamarine" }
but
var_dump($array[0]["id"]);
shows me NULL.
I've tried changing "id" to sth else, tried using ' instead of ", with the same effect, strlen($array[0]["id"]) also returns 0. The second one ("name") works just fine.
Update:
The array is initalized with this code:
$handle = #fopen("stones.csv", "r");
if ($handle) {
while (($row = fgetcsv($handle, 4096, ';')) !== false) {
if (empty($fields)) {
$fields = $row;
continue;
}
foreach ($row as $k=>$value) {
$array[$i][$fields[$k]] = $value;
}
$i++;
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($handle);
}
var_dump($array[0]);
var_dump($array[0]["id"]);
var_dump(array_keys($array[0]));
So there are no modifications between dumps, last three rows return this
array(2) { ["id"]=> string(2) "01" ["name"]=> string(10) "Aquamarine" } NULL array(2) { [0]=> string(5) "id" [1]=> string(4) "name" }
Now I see that there are some invisible characters in the "id" key, so the next question is how to get rid of them?
trim the key using builtin "trim" function. ref: http://php.net/manual/en/function.trim.php
$handle = #fopen("stones.csv", "r");
if ($handle) {
while (($row = fgetcsv($handle, 4096, ';')) !== false) {
if (empty($fields)) {
$fields = $row;
continue;
}
foreach ($row as $k=>$value) {
$array[$i][trim($fields[$k])] = $value;
}
$i++;
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($handle);
}
var_dump($array[0]);
var_dump($array[0]["id"]);
var_dump(array_keys($array[0]));
I am parsing about 500.000 entries into an array $properties:
$properties = array();
$handle = fopen($file_path, "r");
if ($handle) {
while (($str = fgets($handle)) !== false) {
if (strlen($str) && $str[0] == '#') {
$pdate = substr($str, 1);
$date = rtrim($pdate);
$formatted = DateTime::createFromFormat('* M d H:i:s T Y',$date);
}
$str = rtrim ($str, "\n");
$exp = explode ('=', $str);
if(count($exp) == 2){
$exp2 = explode('.', $exp[0]);
if( count($exp2) == 2 ) {
if($exp2[1] == "dateTime"){
$s = str_replace("\\","",$exp[1]);
$d = strtotime($s);
$dateTime = date('Y-m-d H:i:s', $d);
$properties [$exp2[0]][$exp2[1]] = $dateTime;
} else {
$properties [$exp2[0]][$exp2[1]] = $exp[1];
}
} else {
$properties [$exp[0]] = $exp[1];
}
}
}
fclose($handle);
} else {
echo "error";
}
This is working well so far. But I need to split the array into chunks, because otherwise the array is too big to work with it:
$properties_chunk = array_chunk($properties,10000,true);
But now I have the problem that the $properties_chunk array is not created. The system crashes. This is too much. But what can I do now?
The array should look like this in the end:
array(4) {
[0]=>
array(10000) {
["12345"]=>
array(5) {
["dateTime"]=>
string(19) "2016-10-12 19:46:25"
["fileName"]=>
string(46) "monkey.jpg"
["path"]=>
string(149) "Volumes/animals/monkey.jpg"
["size"]=>
string(7) "2650752"
}
["678790"]=>
array(5) {
["dateTime"]=>
string(19) "2016-10-12 14:39:43"
["fileName"]=>
string(45) "elephant.jpg"
["path"]=>
string(171) "Volumes/animals/elephant.jpg"
["size"]=>
string(7) "2306688"
}
... and so on.
If you use array_splice the items will be moved from the input array to the resulting array.
This should mean the memory use should stay the same-ish.
This will do the same as array_chunk but hopefully be less memory hungry.
$arr = [1,2,3,4,5,6,7,8,9,10];
$n = 10000;
$count = (count($arr)/$n)-1; // do not splice the last items in loop
For($i=0; $i<$count; $i++){
$res[] = array_splice($arr, 0,$n);
}
$res[] = array_splice($arr, 0,count($arr));
// here we splice the last items from arr to $res.
// Notice how we splice count($arr) instead of $n.
// If count($arr) == $n we could have done it in the loop.
// But if we assume they are not, array_splice in the loop will create empty items. This line will not.
Var_dump($res, $arr); // $res has all values, $arr is empty
https://3v4l.org/XDpdI
I have an array of imported data:
array(3) {
[1234]=>
array(2) {
["item"]=>
string(6) "scotch"
["type"]=>
string(6) "Spirit"
}
[5678]=>
array(2) {
["item"]=>
string(4) "wine"
["type"]=>
string(7) "Vintner"
}
[9012]=>
array(2) {
["item"]=>
string(11) "soft drinks"
["type"]=>
string(3) "Pop"
}
}
I'm trying to make it say "Its in the Spirit section under code 1234"
I'm new to php so not sure I'm writing the for loop if function correctly. I keep getting "We are out of stock". Man I need a whisky. Help please
my code:
<?php
$row = 1;
$sheet1 = [];
if (($handle = fopen("sheet1.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$sheet1[$data[0]] = [];
$sheet1[$data[0]]['item'] = $data[1];
$sheet1[$data[0]]['type'] = $data[2];
$row++;
}
fclose($handle);
}
var_dump($sheet1);
$string = 'Where is scotch in shop';
echo $string;
$words = explode(' ', $string);
print_r($words);
for ($i = 0; $i < count($words); ++$i) {
if (isset($sheet1[$words[$i]]['item'])) {
echo "Its in the ".$sheet1[$words[$i]]['type']." section marked
under code ".$sheet1[$words[$i]]['key'];
}
}
echo "We are out of stock";
?>
If you change it to a foreach and then check for the existance of the word using in_array() it all looks a litle easier to understand.
foreach ($sheet1 as $key=>$sheet) {
if ( in_array($sheet['item'], $words) ) {
echo "Its in the {$sheet['type']} section marked under code $key";
}
}
Result
Its in the Spirit section marked under code 1234
Im currently trying to write a few words on a file, and then open it.
currently, i do have the following outcome:
When my desired outcome would be something like:
How come it is like that?
TextAr is just some numbers from a textarea. ( one id each line)
code:
$text = preg_replace('/\n+/', "\n", trim($_POST['ids']));
$textAr = explode("\n", $text);
foreach ($textAr as $k=>$v) if(empty(trim($v))) unset($textAr[$k]);
$textAr = array_filter($textAr, 'trim');
$handle = fopen("file.txt", "w");
$saveresult = '';
foreach ($textAr as $line) {
$line = str_replace(' ', '', $line);
$line = preg_replace('/\D/', '', $line);
$result = httpPost($url, $line);
$showID = ($showID ? "".$result['id']." -" : '');
$notexisting = ($showasnull ? 0 : "N/A");
if ($result['manual'] == true) {
$saveresult .= "".$showID." Manual".PHP_EOL;
}
if ($result['hit'] == true && $result['manual'] != true) {
$saveresult .= "".$showID." " . $result['price'] . "".PHP_EOL;
} else if ($result['hit'] == false) {
$saveresult .= "".$showID." ".$notexisting."".PHP_EOL;
}
$saveresult .= "\r\n";
?>
<?PHP }
fwrite($handle, $saveresult);
fclose($handle);
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename('file.txt'));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize('file.txt'));
readfile('file.txt');
EDIT
i removed $saveresult .= "\r\n"; but still same result.
EDIT 2:
example of textAr:
array(2) { [0]=> string(8) "43631132" [1]=> string(8) "43631132" }
example of $result
array(4) { ["id"]=> string(8) "43631132" ["price"]=> int(0) ["hit"]=> bool(false) ["manual"]=> bool(false) }
You can write each line independantly. This way you can check if the line itself is empty before writing.
foreach ($textAr as $line) {
$saveresult = "";
$line = str_replace(' ', '', $line);
$line = preg_replace('/\D/', '', $line);
$result = httpPost($url, $line);
$showID = ($showID ? "".$result['id']." -" : '');
$notexisting = ($showasnull ? 0 : "N/A");
if ($result['manual'] == true) {
$saveresult .= "".$showID." Manual";
}
if ($result['hit'] == true && $result['manual'] != true) {
$saveresult .= "".$showID." " . $result['price'];
} else if ($result['hit'] == false) {
$saveresult .= "".$showID." ".$notexisting;
}
$saveresult = trim($saveresult);
if (!empty($saveresult)) {
fwrite($handle, $saveresult.PHP_EOL);
}
}
fclose($handle);
I'm getting troubles on a simple php function!
What i want to do is:
$text = "this is my data content with many words on it";
I want to write a function that turns the variable string $text as an array like this:
$array = array("this is my", "data content with", "many words on", "it");
In other words, each array piece should have 3 words on it!
This should work:
function split3($text)
{
$array = array();
foreach(explode(' ',$text) as $i=>$word)
{
if($i%3) {
$array[floor($i/3)] .= ' '.$word;
} else {
$array[$i/3] = $word;
}
}
return $array;
}
$text = "this is my data content with many words on it";
var_dump(split3($text));
returns:
array(4) {
[0]=>
string(10) "this is my"
[1]=>
string(17) "data content with"
[2]=>
string(13) "many words on"
[3]=>
string(2) "it"
}
You can do this quite easily with just the one regex. There should be no need for a loop here.
function splitWords($text, $noOfWords = 3) {
$res = array();
preg_match_all('/(\w+\s*){1,'.$noOfWords.'}/', $text, $res);
return $res[0];
}
var_dump(splitWords('one one one two two two thre thre thre four four'));
Result :
array(4) {
[0]=>
string(12) "one one one "
[1]=>
string(12) "two two two "
[2]=>
string(15) "thre thre thre "
[3]=>
string(9) "four four"
}
The basic regex is just
/(\w\s*){1,3}/
if you dont want to catch the remaining 1 or 2 word runs you could just change the count to {3}.
Taken from http://php.net/manual/en/function.preg-split.php:
<?php
/**
* Split a string into groups of words with a line no longer than $max
* characters.
*
* #param string $string
* #param integer $max
* #return array
**/
function split_words($string, $max = 1)
{
$words = preg_split('/\s/', $string);
$lines = array();
$line = '';
foreach ($words as $k => $word) {
$length = strlen($line . ' ' . $word);
if ($length <= $max) {
$line .= ' ' . $word;
} else if ($length > $max) {
if (!empty($line)) $lines[] = trim($line);
$line = $word;
} else {
$lines[] = trim($line) . ' ' . $word;
$line = '';
}
}
$lines[] = ($line = trim($line)) ? $line : $word;
return $lines;
}
?>
There are loads of ways you can do it - this option is probably not the quickest. Are you using this piece of code a lot or not?
how about
<?php
print_r(split3('this is my data content with many words on it'));
function split3($text){
$tmp = explode(" ", $text);
$res = array();
for($i = 0; $i < count($tmp); $i+=3){
$tmpRes = array();
if(isset($tmp[$i])){ $tmpRes[] = $tmp[$i]; }
if(isset($tmp[$i+1])){ $tmpRes[] = $tmp[$i+1]; }
if(isset($tmp[$i+2])){ $tmpRes[] = $tmp[$i+2]; }
$res[] = implode(" ", $tmpRes);
}
return $res;
}
?>
The other answers seem overly verbose. Here's some slightly more idiomatic PHP to do it, and as an added bonus the number of words per chunk is a parameter.
function create_word_chunks($text, $num_words) {
$words = explode(' ', $text);
$start = 0;
$word_chunks = array();
while ($start < count($words)) {
$word_chunks[] = implode(' ', array_slice($words, $start, $num_words));
$start += $num_words;
}
return $word_chunks;
}
$text = "this is my data content with many words on it";
var_dump(create_word_chunks($text, 3));
There should be a way of doing this without regular expressions. Try this:
<?php
//Second argument makes the function return an array of words
$words = str_word_count($text, 1);
foreach(array_chunk($words, 3) as $array){
$pieces[] = implode(' ', $array);
}
?>
$pieces will be an array, each member of which will contain a string with the words. The last member may be shorter than three words depending on the number of words in the original string.