Creating strings of X length based on array - php

I would like to iterate over an array and from that array create a string.
However, each string needs to be of certain size (500 bytes).
So my array looks like:
Array
(
[0] => Array
(
[name] => shirt
[price] => 1.25
)
[1] => Array
(
[name] => car
[price] => 25.10
)
...
)
$str = "";
foreach($arr as $v) {
$str .= "<name>".$v['name']."</name>";
$str .= "<price>".$v['price']."</price>";
}
Output should be something like:
str1 = '<name>shirt</name><price>1.25</price><name>car</name><price>25.10</price>...' // until 500 bytes or less.
str2 = '<name>shirt</name><price>1.25</price><name>car</name><price>25.10</price>...' // until 500 bytes or less.
// I need complete tags. So I can't have a string that looks like:
str = '<name>flower</name><pri';

Save each segment to as less than 500 characters.
$xml = array();
$str = '';
foreach($arr as $v)
{
$temp = "<name>".$v['name']."</name>";
$temp .= "<price>".$v['price']."</price>";
if(mb_strlen($str . $temp) > 500)
{
$xml[] = $str;
$str = '';
}
$str = $temp;
}
$xml[] = $str;
print_r($xml);

str_split sounds like a good candidate.

Related

Convert textarea to array and indented text to nested-arrays in PHP

I am wanting to take text input from a Form Textarea POST in PHP and iterate over each line of text and create a PHP array with the text.
The catch is I want to take lines of text that are indented with 4 spaces before them and make those lines be a sub nested array under the above array item.
I am not sure how to do this at the moment so would appreciate any ideas on it.
// basic demo to show each line of textarea post
$text = $_POST['textarea'];
foreach(explode("\n", $text) as $line) {
echo $line;
echo '<br>';
}
UPDATE
An idea so far something along the lines of this as a start maybe....
$text = $_POST['textarea'];
$in_nested_array = false;
$array = array();
foreach(explode("\n", $text) as $line) {
if($line is 4 spaces){
$in_nested_array = true;
$array[''][$line];
}else{
//if in nested array and new line is not nested, add to root array
if($in_nested_array){
}else{
$in_nested_array = false;
$array[] = $line;
}
}
}
Just a first try:
$str = <<<EOD
bar
baz
meh
lol
tuuut
moo
EOD;
function parse($lines, $depth = 0, $cur = 0)
{
$retVal = array();
for ($i = $cur; $i < count($lines); $i++)
{
$line = $lines[$i];
$lDepth = strlen($line) - strlen(ltrim($line, " "));
if ($lDepth == $depth)
{
$retVal[] = array("line" => ltrim($line, " "));
} elseif ($lDepth == $depth + 4) {
$children = parse($lines, $depth + 4, $i);
$retVal[count($retVal) - 1]["children"] = $children;
$i += count($children);
}
}
return $retVal;
}
$lines = explode("\n", $str);
echo "<pre>";
print_r(parse($lines));
Output:
Array
(
[0] => Array
(
[line] => bar
[children] => Array
(
[0] => Array
(
[line] => baz
[children] => Array
(
[0] => Array
(
[line] => meh
)
[1] => Array
(
[line] => lol
[children] => Array
(
[0] => Array
(
[line] => tuuut
)
)
)
)
)
)
)
[1] => Array
(
[line] => moo
)
)
To seperate by 4 spaces:
$txt = preg_split('/ +/', $text);

PHP regex to match key value pairs from a given string

i hope someone can help.
I have a string as following
$string = 'latitude=46.6781471,longitude=13.9709534,options=[units=auto,lang=de,exclude=[hourly,minutely]]';
Now what i am trying is to create an array out of each key, value pair but badly failing with regex for preg_match_all()
Currently my attempts aren't giving desired results, creating key => value pairs works as long as there are no brackets, but i have absolutely no idea how to achieve a multidimensional array if key contains key/value pairs inside brackets in example.
Array (
[0] => Array
(
[0] => latitude=46.6781471,
[1] => longitude=13.9709534,
[2] => options=[units=si,
[3] => lang=de,
)
[1] => Array
(
[0] => latitude
[1] => longitude
[2] => options=[units
[3] => lang
)
.. and so on
Where in the end i would like to achieve results as following.
Array (
[latitude] => 46.6781471
[longitude] => 13.9709534
[options] => Array
(
[units] => auto
[exclude] => hourly,minutely
)
)
I would appreciate any help or example how i can achieve this from a given string.
Regular expression isn't the right tool to deal with recursive matches. You can write a parser instead of a regex (or use JSON, query string, XML or any other commonly used format):
function parseOptionsString($string) {
$length = strlen($string);
$key = null;
$contextStack = array();
$options = array();
$specialTokens = array('[', ']', '=', ',');
$buffer = '';
$currentOptions = $options;
for ($i = 0; $i < $length; $i++) {
$currentChar = $string[$i];
if (!in_array($currentChar, $specialTokens)) {
$buffer .= $currentChar;
continue;
}
if ($currentChar == '[') {
array_push($contextStack, [$key, $currentOptions]);
$currentOptions[$key] = array();
$currentOptions = $currentOptions[$key];
$key = '';
$buffer = '';
continue;
}
if ($currentChar == ']') {
if (!empty($buffer)) {
if (!empty($key)) {
$currentOptions[$key] = $buffer;
} else {
$currentOptions[] = $buffer;
}
}
$contextInfo = array_pop($contextStack);
$previousContext = $contextInfo[1];
$thisKey = $contextInfo[0];
$previousContext[$thisKey] = $currentOptions;
$currentOptions = $previousContext;
$buffer = '';
$key = '';
continue;
}
if ($currentChar == '=') {
$key = $buffer;
$buffer = '';
continue;
}
if ($currentChar == ',') {
if (!empty($key)) {
$currentOptions[$key] = $buffer;
} else if (!empty($buffer)) {
$currentOptions[] = $buffer;
}
$buffer = '';
$key = '';
continue;
}
}
if (!empty($key)) {
$currentOptions[$key] = $buffer;
}
return $currentOptions;
}
this gives the following output:
print_r(parseOptionsString($string));
Array
(
[latitude] => 46.6781471
[longitude] => 13.9709534
[options] => Array
(
[units] => auto
[lang] => de
[exclude] => Array
(
[0] => hourly
[1] => minutely
)
)
)
Note also that you want a special syntax for arrays with only comma separated values (exclude=[hourly,minutely] becomes exclude => hourly,minutely and not exclude => array(hourly, minutely)). I think this is an inconsistency in your format and I wrote the parser with the "correct" version in mind.
If you don't want parser you can also try this code. It converts your string to JSON and decode to array. But as others said, I think you should try the approach with JSON. If you're sending this string by XmlHttpRequest in JavaScript it will not be hard to create proper JSON code to send.
$string = 'latitude=46.6781471,longitude=13.9709534,options=[units=auto,lang=de,exclude=[hourly,minutely]]';
$string = preg_replace('/([^=,\[\]\s]+)/', '"$1"', $string);
$string = '{' . $string . '}';
$string = str_replace('=', ':', $string);
$string = str_replace('[', '{', $string);
$string = str_replace(']', '}', $string);
$string = preg_replace('/({[^:}]*})/', '|$1|', $string);
$string = str_replace('|{', '[', $string);
$string = str_replace('}|', ']', $string);
$result = json_decode($string, true);
print_r($result);

How can I build a dynamic array from a string in PHP?

I'm trying to create an array in PHP that has the structure defined by a string. It will loop through and use the first value as the value and the second value as the quantity. For instance the 1|3 will have the value of 1, 3 times and then loop to the next in the string.
Here is what I have so far -
<?php
$quantity = 10;
$string = '1|3,2|3';
$overall_types = array( );
$types = explode( ',', $string );
for ( $i = 1; $i <= $quantity; $i++ )
{
$qc = explode( '|', $types[0] );
$overall_types[$i] = $qc[0];
}
echo '<pre>';
print_r ( $overall_types );
echo '</pre>';
and that gets me
Array
(
[1] => 1
[2] => 1
[3] => 1
[4] => 1
[5] => 1
[6] => 1
[7] => 1
[8] => 1
[9] => 1
[10] => 1
)
but, I want the result to be
Array
(
[1] => 1
[2] => 1
[3] => 1
[4] => 2
[5] => 2
[6] => 2
[7] => 1
[8] => 1
[9] => 1
[10] => 2
)
I'm not sure how to easily switch between the exploded values.
Thanks.
You're not using the repetition count at all from what I see. Achieving this using a straight-forward approach is tricky and probably not necessary when there's a simpler way to do this.
<?php
function buildReps($string) {
$array = [];
$overall_types = array( );
$types = explode( ',', $string );
foreach ($types as $type) {
$qc = explode( '|', $type );
$array = array_merge($array, array_fill(0, $qc[1], $qc[0]));
}
return $array;
}
function buildAllReps($string, $quantity) {
$array = [];
while (count($array) < $quantity) {
$array = array_merge($array, buildReps($string));
}
return array_slice($array, 0, $quantity);
}
$quantity = 10;
$string = '1|3,2|3';
echo '<pre>';
print_r ( buildAllReps($string, $quantity) );
echo '</pre>';
The first function builds the array once based on the $string defintion. The second one just merges the results from the first one until you reach quantity and then stops and returns the correct quantity of items back.
The above outputs:
Array
(
[0] => 1
[1] => 1
[2] => 1
[3] => 2
[4] => 2
[5] => 2
[6] => 1
[7] => 1
[8] => 1
[9] => 2
)
Example in https://eval.in/629556
Beware of infinite loops which may occur if the definition supplied by $string does not produce a non-empty array.
There's a better way to do string to array in PHP.
You can use either serialize and unserialize or json_encode and json_decode to create strings and then to convert them to array. This is far better than what you would want to implement, because those methods are in the php core, which means they are faster.
http://php.net/serialize
http://php.net/manual/ro/function.json-encode.php
From json string to array, you will need to do something like this:
$json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
// extra boolean parameter set to true to return array instead of json object
$array = json_decode($json, true);
<?php
$quantity = 10;
$string = '1|3,2|3';
$overall_types = [];
$types = explode( ',', $string );
for($c = 0; $c < $quantity; $c++) {
foreach ($types as $currentType) {
$qc = explode( '|', $currentType );
for ($i = 0; $i < $qc[1]; $i++) {
$overall_types[] = $qc[0];
}
}
}
$overall_types = array_slice($overall_types,0,$quantity);
echo '<pre>';
print_r ( $overall_types );
echo '</pre>';
This should give you the output that you need.
Not going into micro benchmarking here but you could probably also preg_replace /g the \w|\d+, multipliers by their full string representation and only preg_split the entire string into an array after this step. Like so:
$string = '1|3,2|3';
print_r(str_split(preg_replace_callback('/(\w)\|(\d+),?/', function($a) {
return str_repeat($a[1], $a[2]);
}, $string)));
Less array handling and potentially faster.
I would however suggest to reconsider the initial string representation and look for a better approach. Why is this format needed if it needs to be converted anyway?

PHP reading data input from a text file

I have a text file which I must read, and use the data from.
3
sam 99912222
tom 11122222
harry 12299933
sam
edward
harry
How can I create an array of these strings in the following form?
array(
"name" => "number"
...
)
I tried this:
$handle = fopen("file.txt", "r");
fscanf($handle, "%d %d", $name, $number);
What then? No matter what I try, it only works for the first line.
sam 99912222
Added codes to have both types of output - ignoring and including the lines that don't have name-value pairs. Check them out below
This code goes through each line and gets only the ones that have both name and value (something[space]something)):
//$lines = ... each line of the file in an array
$vals = array();
foreach($lines as $v){
$tmp = explode(' ', $v);
if(count($tmp) > 1){
$vals[trim($tmp[0])] = trim($tmp[1]); // trim to prevent garbage
}
}
print_r($vals);
It will output this:
Array
(
[sam] => 99912222
[tom] => 11122222
[harry] => 12299933
)
See the code in action here.
If you need the values even if they didn't come in pairs, do it like this:
//$lines = ... each line of the file
$vals = array();
foreach($lines as $v){
$tmp = explode(' ', $v);
$name = '';
$number = '';
$tmp[0] = trim($tmp[0]);
if(count($tmp) > 1){
$name = $tmp[0];
$number = trim($tmp[1]);
}else{
if(is_numeric($tmp[0])){
$number = $tmp[0];
}else{
$name = $tmp[0];
}
}
$vals[] = array(
'name' => $name,
'number' => $number
);
}
print_r($vals);
And the output:
Array
(
[0] => Array
(
[name] =>
[number] => 3
)
[1] => Array
(
[name] => sam
[number] => 99912222
)
[2] => Array
(
[name] => tom
[number] => 11122222
)
[3] => Array
(
[name] => harry
[number] => 12299933
)
[4] => Array
(
[name] => sam
[number] =>
)
[5] => Array
(
[name] => edward
[number] =>
)
[6] => Array
(
[name] => harry
[number] =>
)
See the code in action here.
Data in file are inconsistent, best of is to use regex to identify what data you've got from each line.
$lines = file('file.txt'); // this will open file and split them into lines
$items = array();
foreach($lines as $line){
$name = null;
$number = null;
$nameFound = preg_match("|([A-Za-z]+)|", $line, $matches);
if($nameFound){
$name = $matches[0];
}
$numberFound = preg_match("|([0-9]+)|", $line, $matches);
if($numberFound){
$number = $matches[0];
}
$items[] = array('name' => $name, 'number' => $number);
}
Then in items you should find parsed data from file.
To make it just extract full format data just change lines with regex into one line like this:
$lines = file('file.txt'); // this will open file and split them into lines
$items = array();
foreach($lines as $line){
$userFound = preg_match("/([A-Za-z]+) ([0-9]+)/", $line, $matches);
if($userFound){
$items[$matches[1]] = $matches[2];
}
}
With the Algorithm below, you can simply parse each individual line of the Text-File Contents into an array with the 1st Word or Digit(s) on each line as the Key and the 2nd Word as the Value. When the 2nd word or group of words do not exist, a NULL is assigned to that Key. For re-usability, this algorithm has been encapsulated into a Function. Here you go:
<?php
function parseTxtFile($txtFile){
$arrTxtContent = [];
if(!file_exists($txtFile)){ return null;}
$strFWriteTxtData = file_get_contents($txtFile);
if(empty($strFWriteTxtData)){return null;}
$arrFWriteInfo = explode("\n", $strFWriteTxtData);
foreach($arrFWriteInfo as $iKey=>$lineData){
$arrWriteData = explode(", ", $lineData);
foreach($arrWriteData as $intKey=>$strKeyInfo){
preg_match("#(^[a-z0-9_A-Z]*)(\s)(.*$)#i", $strKeyInfo, $matches);
preg_match("#(^[a-z0-9_A-Z]*)(\s*)?$#i", $strKeyInfo, $matches2);
if($matches) {
list(, $key, $null, $val) = $matches;
if (!array_key_exists($key, $arrTxtContent)) {
$arrTxtContent[$key] = $val;
}else{
$iKey = $intKey + 1;
$key = $key . "_{$iKey}";
$arrTxtContent[$key] = $val;
}
}else if($matches2) {
list(, $key, $null) = $matches2;
if (!array_key_exists($key, $arrTxtContent)) {
$arrTxtContent[$key] = null;
}else{
$key = preg_match("#_\d+#", $key, $match)? $key . $match[0] : "{$key}_1";
$arrTxtContent[$key] = null;
}
}
}
}
return $arrTxtContent;
}
var_dump(parseTxtFile(__DIR__ . "/data.txt"));
Just call the function parseTxtFile($txtFile) passing it the path to your text File and it will return an Array that looks something like below:
array (size=7)
3 => null
'sam' => string '99912222' (length=8)
'tom' => string '11122222' (length=8)
'harry' => string '12299933' (length=8)
'sam_1' => null
'edward' => null
'harry_1' => null
Hope this could help a bit....
Cheers & Good-Luck ;-)

PHP foreach() loop

$string = "The complete archive of The New York Times can now be searched from NYTimes.com " //the actual input is unknown, it would be read from textarea
$size = the longest word length from the string
I assigned and initialized array in for loop, for example array1, array2 ....arrayN, here is how i did
for ($i = 1; $i <= $size; $i++) {
${"array" . $i} = array();
}
so the $string would be divided in the length of the word
$array1 = [""];
$array2 = ["of", "be", ...]
$array3 = ["the", "can", "now", ...] and so on
So, my question is how to assign in simple for loop or foreach loop $string value to $array1, $array2, $array3 ....., since the input text or the size of the longest word is unknown
I'd probably start with $words = explode(' ', $string)
then sort the string by word length
usort($words, function($word1, $word2) {
if (strlen($word1) == strlen($word2)) {
return 0;
}
return (strlen($word1) < strlen($word2)) ? -1 : 1;
});
$longestWordSize = strlen(last($words));
Loop over the words and place in their respective buckets.
Rather than separate variables for each length array, you should consider something like
$sortedWords = array(
1 => array('a', 'I'),
2 => array('to', 'be', 'or', 'is'),
3 => array('not', 'the'),
);
by looping over the words you don't need to know the maximum word length.
The final solution is as simple as
foreach ($words as $word) {
$wordLength = strlen($word);
$sortedWords[ $wordLength ][] = $word;
}
You could use something like this:
$words = explode(" ", $string);
foreach ($words as $w) {
array_push(${"array" . strlen($w)}, $w);
}
This splits up $string into an array of $words and then evaluates each word for length and pushes that word to the appropriate array.
you can use explode().
$string = "The complete archive of The New York Times can now be searched from NYTimes.com " ;
$arr=explode(" ",$string);
$count=count($arr);
$big=0;
for ($i = 0; $i < $count; $i++) {
$p=strlen($arr[$i]);
if($big<$p){ $big_val=$arr[$i]; $big=$p;}
}
echo $big_val;
Just use the word length as the index and append [] each word:
foreach(explode(' ', $string) as $word) {
$array[strlen($word)][] = $word;
}
To remove duplicates $array = array_map('array_unique', $array);.
Yields:
Array
(
[3] => Array
(
[0] => The
[2] => New
[3] => can
[4] => now
)
[8] => Array
(
[0] => complete
[1] => searched
)
[7] => Array
(
[0] => archive
)
[2] => Array
(
[0] => of
[1] => be
)
[4] => Array
(
[0] => York
)
[5] => Array
(
[0] => Times
)
)
If you want to re-index the main array use array_values() and to re-index the subarrays use array_map() with array_values().

Categories