PHP Regex Match Troubles - php

I have some data in a string in the format key: value key: value key: value etc...
I'm trying to turn it into an array using a regex match. The keys are all uppercase letters directly followed by a colon. Then there is a space and the value starts. This is then followed by a space and then the next key. The value can contain upper/lowercase letters, numbers, space, comma or equals sign.
For example, I'd like this input string:
NAME: Name of Item COLOR: green SIZE: 40
Turned into this array:
newArray[NAME] = Name of Item
newArray[COLOR] = green
newArray[SIZE] = 40
Any help is much appreciated. Also I don't have access to the formatting of the input, or I'd make this a lot easier on myself.

A generic solution:
$str = 'NAME: Name of Item COLOR: green SIZE: 40';
$split = preg_split('/([A-Z]+):/', $str, -1,
PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
echo 'Split Array is: ' . var_export($split, true);
$newArray = array();
// Stick the key and value together (processing two entries at a time.
for ($i = 0; $i < count($split) - 1; $i = $i + 2)
{
$newArray[$split[$i]] = trim($split[$i + 1]); // Probably trim them.
}
echo 'New Array is: ' . var_export($newArray, true);

I'd suggest
$str = "NAME: Name of Item COLOR: green SIZE: 40";
preg_match_all('~([A-Z]+):(.+?)(?=[A-Z]+:|$)~', $str, $m, PREG_SET_ORDER);
foreach($m as $e)
$result[$e[1]] = trim($e[2]);
print_r($result);

Related

how to get first two word from a sentence using php for loop

I am trying to get first two word from a sentence using php
$inp_val= "this is our country";
output will be : this is
// this input value has different string as Like: this, this is our, this name is mine
// i need to get only first two word or if anyone wrote only one word then i got same word but if any one wrote two or more word then it will collect only first two word..
I am trying with below code but it won't work properly..
$words = explode(' ', $inp_val);
$shop_name = "";
if (str_word_count($words) == 1) {
$shop_name .= mb_substr($words[0], 0, 1);
} else {
for ($i = 0; $i < 2; $i++) {
$w = $words[$i];
$shop_name .= mb_substr($w, 0, 1);
}
}
After exploding the input value by space (as you have done), you can use array_slice to extract the 2 first elements, then use the implode to concat the 2 elements as a string.
$inp_val = "this is our country";
$shop_name = implode(" ", array_slice(explode(' ', $inp_val), 0, 2));
echo $shop_name;
//OUTPUT: this is
This method that uses array_slice work well for one or more words

How can I split a string into three word chunks?

I need to split a string in every three words using PHP
"This is an example of what I need."
The output would be:
This is an
is an example
an example of
example of what
of what I
what I need
I have this example with Java
String myString = "This is an example of what I need.";
String[] words = myString.split("\\s+");
for (int i = 0; i < words.length; i++) {
String threeWords;
if (i == words.length - 1)
threeWords = words[i];
else if(i == words.length - 2)
threeWords = words[i] + " " + words[i + 1];
else
threeWords = words[i] + " " + words[i + 1] + " " + words[i + 2];
System.out.println(threeWords);
}
Solution that use explode, array_slice and implode.
$example = 'This is an example of what I need.';
$arr = explode(" ",$example);
foreach($arr as $key => $word){
//if($key == 0) continue;
$subArr = array_slice($arr,$key,3);
if(count($subArr) < 3) break;
echo implode(" ",$subArr)."<br>\n";
}
Output:
This is an
is an example
an example of
example of what
of what I
what I need.
If you want to suppress the first output with This, remove the comment in the line
//if($key == 0) continue;
If the example can have less than 3 words and these should be output then the line with the break must be as follows:
if(count($subArr) < 3 AND $key != 0) break;
For strings that are not only separated by single spaces, preg_split is recommended. Example:
$example = "This is an example of what I need.
Sentence,containing a comma and Raphaël.";
$arr = preg_split('/[ .,;\r\n\t]+/u', $example, 0, PREG_SPLIT_NO_EMPTY);
foreach($arr as $key => $word){
$subArr = array_slice($arr,$key,3);
if(count($subArr) < 3) break;
echo implode(" ",$subArr)."<br>\n";
}
Output:
This is an
is an example
an example of
example of what
of what I
what I need
I need Sentence
need Sentence containing
Sentence containing a
containing a comma
a comma and
comma and Raphaël
To include only words (notice the fullstop is removed from the last trigram), use str_word_count() to form the array of strings.
Then you need to loop while there are three elements to print.
Code: (Demo)
$example = 'This is an example of what I need.';
$words = str_word_count($example, 1);
for ($x = 0; isset($words[$x + 2]); ++$x) {
printf("%s %s %s\n", $words[$x], $words[$x + 1], $words[$x + 2]);
}
Output:
This is an
is an example
an example of
example of what
of what I
what I need
If you don't like printf(), you could echo implode(' ', [the three elements]).
If you want to print a single string of words when there are less than 3 total words in the string, then you could use a post-test loop. Demo
And then, of course, if we going to stumble down the rocky road of "what is a word", then an ironclad definition of "what is a word" will need to be defined and then a regex (potentially with multibyte support) will need to be suitably crafted. Basic Demo

How to display specific letters from a list of words in a loop?

I received this challenge in an interview and I would like some help solving it.
Using the input string: PHP CODING TECH, produce the following output.
PCT
PHCT
PHPCT
PHPCOT
PHPCODT
PHPCODIT
PHPCODINT
PHPCODINGT
PHPCODINGTE
PHPCODINGTEC
PHPCODINGTECH
As I understand it, the logic is to explode the input string on the spaces and then in a loop structure, display the leading letter(s) of each word as a single string. During each iteration (after the first), the earliest incomplete word displays an additional leading letter.
This is my coding attempt:
$str = "PHP CODING TECH";
$a = explode(' ', $str);
for ($i=0; $i < count($a); $i++) {
for ($j=0; $j < strlen($a[$i]) ; $j++) {
//echo "<pre>";
$b[$i][$j] = explode(' ', $a[$i][$j]);
}
}
echo "<pre>";
print_r($b);
Code: (Demo) (or with DO-WHILE())
$input = "PHP CODING TECH";
$counters = array_fill_keys(explode(' ', $input), 1); // ['PHP' => 1, 'CODING' => 1, 'TECH' => 1]
$bump = false; // permit outer loop to run
while (!$bump) { // while still letters to output....
$bump = true; // stop after this iteration unless more letters to output
foreach ($counters as $word => &$len) { // $len is mod-by-ref for incrementing
echo substr($word, 0, $len); // echo letters using $len
if ($bump && isset($word[$len])) { // if no $len has been incremented during inner loop...
++$len; // increment this word's $len
$bump = false; // permit outer loop to run again
}
}
echo "\n"; // separate outputs
}
Output:
PCT
PHCT
PHPCT
PHPCOT
PHPCODT
PHPCODIT
PHPCODINT
PHPCODINGT
PHPCODINGTE
PHPCODINGTEC
PHPCODINGTECH
Explanation:
I am generating an array of words and initial lengths from the exploded input string. $bump is dual-purpose; it not only controls the outer loop, it also dictates the word which gets a length increase within the inner loop. $len is "modifiable by reference" so that any given word's $len value can be incremented and stored for use in the next iteration. isset() is used on $word[$len] to determine if the current word has more available letters to output in the next iteration; if not, the next word gets a chance (until all words are fully displayed).
And while I was waiting for this page to be reopened, I whacked together an alternative method:
$input = "PHP CODING TECH";
$words = explode(' ', $input); // generates: ['PHP', 'CODING', 'TECH']
$master = ''; // initialize for first offset and then concatenation
foreach ($words as $word) {
$offsets[] = strlen($master); // after loop, $offsets = [0, 3, 9]
$master .= $word; // after loop, $master = 'PHPCODINGTECH'
}
$master_offsets = range(0, strlen($master)); // generates: [0,1,2,3,4,5,6,7,8,9,10,11,12]
do {
foreach ($offsets as $offset) {
echo $master[$offset];
}
echo "\n";
} while ($master_offsets !== ($offsets = array_intersect($master_offsets, array_merge($offsets, [current(array_diff($master_offsets, $offsets))])))); // add first different offset from $master_offsets to $offsets until they are identical

Find the word in a sentence with maximum specific character count

I am new to PHP Development and finally with the help of SO I am able to write a program for finding word in a sentence with maximum specific character count.
Below is what I have tried:
<?php
// Program to find the word in a sentence with maximum specific character count
// Example: "O Romeo, Romeo, wherefore art thou Romeo?”
// Solution: wherefore
// Explanation: Because "e" came three times
$content = file_get_contents($argv[1]); // Reading content of file
$max = 0;
$arr = explode(" ", $content); // entire array of strings with file contents
for($x =0; $x<count($arr); $x++) // looping through entire array
{
$array[$x] = str_split($arr[$x]); // converting each of the string into array
}
for($x = 0; $x < count($arr); $x++)
{
$count = array_count_values($array[$x]);
$curr_max = max($count);
if($curr_max > $max)
{
$max = $curr_max;
$word = $arr[$x];
}
}
echo $word;
?>
Question: Since I am new to PHP development I don't know the optimization techniques. Is there anyway I can optimize this code? Also, Can I use regex to optimize this code further? Kindly guide.
I love coding this type of mini-challenges in the minimum lines of code :D. So here is my solution:
function wordsWithMaxCharFrequency($sentence) {
$words = preg_split('/\s+/', $sentence);
$maxCharsFrequency = array_map (function($word) {
return max(count_chars(strtolower($word)));
}, $words);
return array_map(function($index) use($words) {
return $words[$index];
}, array_keys($maxCharsFrequency, max($maxCharsFrequency)));
}
print_r(wordsWithMaxCharFrequency("eeee yyyy"));
//Output: Array ( [0] => eeee [1] => yyyy )
print_r(wordsWithMaxCharFrequency("xx llll x"));
//Output: Array ( [0] => llll )
Update1:
If you want to get only A-Za-z words use the following code:
$matches = [];
//a word is either followed by a space or end of input
preg_match_all('/([a-z]+)(?=\s|$)/i', $sentence, $matches);
$words = $matches[1];
Just a contribution that could inspire you :D!
Good Luck.

Split a string, remember the positions of splitting

Assume I have the following string:
I have | been very busy lately and need to go | to bed early
By splitting on "|", you get:
$arr = array(
[0] => I have
[1] => been very busy lately and need to go
[2] => to bed early
)
The first split is after 2 words, and the second split 8 words after that. The positions after how many words to split will be stored: array(2, 8, 3). Then, the string is imploded to be passed on to a custom string tagger:
tag_string('I have been very busy lately and need to go to bed early');
I don't know what the output of tag_string will be exactly, except that the total words will remain the same. Examples of output would be:
I have-nn been-vb very-vb busy lately and-rr need to-r go to bed early-p
I-ee have been-vb very busy-df lately-nn and need-f to go to bed-uu early-yy
This will lengthen the string by an unknown number of characters. I have no control over tag_string. What I know is (1) the number of words will be the same as before and (2) the array was split after 2, and thereafter after 8 words, respectively. I now need a solution explode the tagged string into the same array as before:
$string = "I have-nn been-vb very-vb busy lately and-rr need to-r go to bed early-p"
function split_string_again() {
// split after 2nd, and thereafter after 8th word
}
With output:
$arr = array(
[0] => I have-nn
[1] => been-vb very-vb busy lately and-rr need to-r go
[2] => to bed early-p
)
So to be clear (I wasn't before): I cannot split by remembering the strpos, because strpos before and after the string went through the tagger, aren't the same. I need to count the number of words. I hope I have made myself more clear :)
You wouldn't want to count the number of words, you would want to count the string length (strlen). If it is the same string without the pipes, then you want to split it with substr after a certain amount.
$strCounts = array();
foreach ($arr as $item) {
$strCounts[] = strlen($item);
}
// Later on.
$arr = array();
$i = 0;
foreach ($strCounts as $count) {
$arr[] = substr($string, $i, $count);
$i += $count; // increment the start position by the length
}
I have not tested this, simply a "theory" and probably has some kinks to work out. There may be a better way to go about it, I just don't know it.
Interesting question, although I think the rope data structure still applies it might be a little overkill since word placement won't change. Here is my solution:
$str = "I have | been very busy lately and need to go | to bed early";
function get_breaks($str)
{
$breaks = array();
$arr = explode("|", $str);
foreach($arr as $val)
{
$breaks[] = str_word_count($val);
}
return $breaks;
}
$breaks = get_breaks($str);
echo "<pre>" . print_r($breaks, 1) . "</pre>";
$str = str_replace("|", "", $str);
function rebreak($str, $breaks)
{
$return = array();
$old_break = 0;
$arr = str_word_count($str, 1);
foreach($breaks as $break)
{
$return[] = implode(" ", array_slice($arr, $old_break, $break));
$old_break += $break;
}
return $return;
}
echo "<pre>" . print_r(rebreak($str, $breaks), 1) . "</pre>";
echo "<pre>" . print_r(rebreak("I have-nn been-vb very-vb busy lately and-rr need to-r go to bed early-p", $breaks), 1) . "</pre>";
Let me know if you have any questions, but it is pretty self explanatory. There are definitely ways to improve this as well.
I'm not quite sure I understood what you actually wanted to achieve. But here are a couple of things that might help you:
str_word_count() counts the number of words in a string. preg_match_all('/\p{L}[\p{L}\p{Mn}\p{Pd}\x{2019}]*/u', $string, $foo); does pretty much the same, but on UTF-8 strings.
strpos() finds the first occurrence of a string within another. You could easily find the positions of all | with this:
$pos = -1;
$positions = array();
while (($pos = strpos($string, '|', $pos + 1)) !== false) {
$positions[] = $pos;
}
I'm still not sure I understood why you can't just use explode() for this, though.
<?php
$string = 'I have | been very busy lately and need to go | to bed early';
$parts = explode('|', $string);
$words = array();
foreach ($parts as $s) {
$words[] = str_word_count($s);
}

Categories