Array not being updated outside of foreach loop - php

I have a piece of code that I'm struggling with. I'm still on my first steps so it's entirely possible that some silly mistake is causing this.
I want to turn each first character of each word into uppercase, but for some reason it is not working and I cannot get it figured out.
$split = explode(" ",$string);
foreach ($split as $word) {
if (ord($word[0]) >= 97 & ord($word[0]) <= 122){
$word[0] = chr(ord($word[0]) - 32);
}}
return $string;
}

You should handle this a little differently.
Let's create our split first:
$words = explode(' ', $words_string);
Now let's loop through these words and remember their index by using the $key param.
foreach($words as $index => $word) { //So we remember the key in the array using $k => $v
$words[$index] = ucfirst($word); //This will uppercase the first letter.
}

The reason why it's not working is explained in the question i've linked.
However in your case the solution is much more simple. You can just use ucwords() function or mb_convert_case() with MB_CASE_TITLE if you work with multibyte strings.

PHP provides in-built function that help you convert every word's first character to uppercase of the string without exploding and iterating through.
ucwords( $string );
EDIT: Let us include a sample to help you out what would be the output:
echo ucwords("Hi this is just a simple test of converting each word's first charater to uppercase!");
will return
Hi This Is Just A Simple Test Of Converting Each Word's First Charater To Uppercase!

Related

php regex find substring in substring

I am still playing around for one project with matching words.
Let assume that I have a given string, say maxmuster . Then I want to mark this part of my random word maxs which are in maxmuster in the proper order, like the letters are.
I wil give some examples and then I tell what I already did. Lets keep the string maxmuster. The bold part is the matched one by regex (best would be in php, however could be python, bash, javascript,...)
maxs
Mymaxmuis
Lemu
muster
Of course also m, u, ... will be matched then. I know that, I am going to fix that later. However, the solution, I though, should not so difficult, so I try to divide the word in groups like this:
/(maxmuster)?|(maxmuste)?|(maxmust)?|(maxmus)?|(maxmu)?|(maxm)?|(max)?|(ma)?|(m)?/gui
But then I forgot of course the other combinations, like:
(axmuster)(xmus) and so on. Did I really have to do that, or exist there a simple regex trick, to solve this question, like I explained above?
Thank you very much
Sounds like you need string intersection. If you don't mind non regex idea, have a look in Wikibooks Algorithm Implementation/Strings/Longest common substring PHP section.
foreach(["maxs", "Mymaxmuis", "Lemu", "muster"] AS $str)
echo get_longest_common_subsequence($str, "maxmuster") . "\n";
max
maxmu
mu
muster
See this PHP demo at tio.run (caseless comparison).
If you need a regex idea, I would join both strings with space and use a pattern like this demo.
(?=(\w+)(?=\w* \w*?\1))\w
It will capture inside a lookahead at each position before a word character in the first string the longest substring that also matches the second string. Then by PHP matches of the first group need to be sorted by length and the longest match will be returned. See the PHP demo at tio.run.
function get_longest_common_subsequence($w1="", $w2="")
{
$test_str = preg_quote($w1,'/')." ".preg_quote($w2,'/');
if(preg_match_all('/(?=(\w+)(?=\w* \w*?\1))\w/i', $test_str, $out) > 0)
{
usort($out[1], function($a, $b) { return strlen($b) - strlen($a); });
return $out[1][0];
}
}
TL;DR
Using Regular Expressions:
longestSubstring(['Mymaxmuis', 'axmuis', 'muster'], buildRegexFrom('maxmuster'));
Full snippet
Using below regex you are able to match all true sub-strings of string maxmuster:
(?|((?:
m(?=a)
|(?<=m)a
|a(?=x)
|(?<=a)x
|x(?=m)
|(?<=x)m
|m(?=u)
|(?<=m)u
|u(?=s)
|(?<=u)s
|s(?=t)
|(?<=s)t
|t(?=e)
|(?<=t)e
|e(?=r)
|(?<=e)r
)+)|([maxmuster]))
Live demo
You have to cook such a regex from a word like maxmuster so you need a function to call it:
function buildRegexFrom(string $word): string {
// Split word to letters
$letters = str_split($word);
// Creating all side of alternations in our regex
foreach ($letters as $key => $letter)
if (end($letters) != $letter)
$regex[] = "$letter(?={$letters[$key + 1]})|(?<=$letter){$letters[$key + 1]}";
// Return whole cooked pattern
return "~(?|((?>".implode('|', $regex).")+)|([$word]))~i";
}
To return longest match you need to sort results according to matches length from longest to shortest. It means writing another piece of code for it:
function longestSubstring(array $array, string $regex): array {
foreach ($array as $value) {
preg_match_all($regex, $value, $matches);
usort($matches[1], function($a, $b) {
return strlen($b) <=> strlen($a);
});
// Store longest match being sorted
$substrings[] = $matches[1][0];
}
return $substrings;
}
Putting all things together:
print_r(longestSubstring(['Mymaxmuis', 'axmuis', 'muster'], buildRegexFrom('maxmuster')));
Outputs:
Array
(
[0] => maxmu
[1] => axmu
[2] => muster
)
PHP live demo
Here is my take on this problem using regex.
<?php
$subject="maxmuster";
$str="Lemu";
$comb=str_split($subject); // Split into single characters.
$len=strlen($subject);
for ($i=2; $i<=$len; $i++){
for($start=0; $start<$len; $start++){
$temp="";
$inc=$start;
for($j=0; $j<$i; $j++){
$temp=$temp.$subject[$inc];
$inc++;
}
array_push($comb,$temp);
}
}
echo "Matches are:\n";
for($i=0; $i<sizeof($comb); $i++){
$pattern = "/".$comb[$i]."/";
if(preg_match($pattern,$str, $matches)){
print_r($matches);
};
}
?>
And here is an Ideone Demo.

Is right using preg_match to search word that contain specific letters?

I have a group of letters, for example :
$word='estroaroint';
that can be arranged to be words like :
- store
- train
- restoration
- ...etc
They can be found in my file list 'dictionary.txt'.
A letter only can only be used once.
How to write a php script able to perform that?
I would try to manage it with this function: strpbrk() http://php.net/manual/en/function.strpbrk.php
It isn't really possible to do that in one step with a regex. However, it is possible to do it in two steps:
the first step find all the words in the dictionary that only contains the letters.
the second step filter words where letters are repeated.
Example (only for ascii range):
$pattern = '~\b[' . $word . ']{1,' . strlen($word) . '}+\b~';
if (preg_match_all($pattern, $dictionary, $m)) {
$chars = count_chars ($word, 1);
$result = array_filter($m[0], function ($i) use ($chars) {
foreach (count_chars($i, 1) as $k=>$v) {
if ($v > $chars[$k]) return false;
}
return true;
});
print_r($result);
}
PHP links: array_filter - count_chars
Note: to extend this script to multibyte characters, you need to write your own function mb_count_chars (since this function doesn't exist) that splits a multibyte string (you can use for example mb_substr, mb_strlen and a loop, or preg_split with ~(?=.)~u and the PREG_SPLIT_NO_EMPTY option). You need to add the u modifier to the regex pattern too and to change strlen to its multybyte equivalent.

Separating Words in a TextBox Into an Array

In PHP, how would one take a string and separate the words into an array? Is there a way to split them by the spaces in the string? Also, how would you check if a word in an array starts with a character? The idea would be to have a textbox with come normal words and a hashtag. The PHP script would maybe underline or change the color of the hashtag when you submit the form. It would basically underline any word that started with a hash. Sorry if this doesn't make any sense.
To convert a string to an array, use PHP's explode function:
$array = explode(' ', $string);
To examine whether each word begins with a certain character, you can use strpos in a loop:
// Pick a letter
$char = 'a';
foreach ($array as $word) {
if (strpos($word, $char) === 0) {
// Echo out what you want
echo "$word contains $char\r\n";
// Halt loop if necessary:
break;
}
}

Temporarily remove labels/tags and re-insert them later on

Consider the following string
$input = "string with {LABELS} between brackets {HERE} and {HERE}";
I want to temporarily remove all labels (= whatever is between curly braces) so that an operation can be performed on the rest of the string:
$string = "string with between brackets and";
For arguments sake, the operation is concatenate every word that starts with 'b' with the word 'yes'.
function operate($string) {
$words = explode(' ', $string);
foreach ($words as $word) {
$output[] = (strpos($word, 0, 1) == 'b') ? "yes$word" : $word;
}
return implode(' ', $output);
}
The output of this function would be
"string with yesbetween yesbrackets and"
Now I want to insert the temporarily deleted labels back into place:
"string with {LABELS} yesbetween yesbrackets {HERE} and {HERE}"
My question is: how can I accomplish this? Important: I am not able to alter operate(), so the solution should contain a wrapper function around operate() or something. I have been thinking about this for quite a while now, but am confused as to how to do this. Could you help me out?
Edit: it would be too much to put the actual operate() in this post. It will not really add value (except make the post longer). There is not much difference between the output of operate() here and the real one. I will be able to translate any ideas from here, to the real-world situation :-)
The answer to this depends on wether or not you are able to understand operate(), even if you can't change it.
If you have absolutely no insight into operate(), your problem is simply unsolvable: To reinsert your labels you need one of
Their offset or relative position (You can't know them, if you don't know operate())
A marker for their place (You can't have them, if you don't know how operate() will work on them)
If you have at least some insight into operate(), this becomes something between solvable and easy:
If operate($a . $b)==operate($a) . operate($b), then you just split your original input by the labels, run the non-label parts through operate(), but obviously not the labels, then reassemble
If operate() is guaranteed to let a placeholder string, that itself is guaranteed to be not part of the normal input ("\0" and friends come to mind) alone, then you extract your labels in order, replace them by the placeholder, run the result through operate() and later replace the placeholder by your saved labels (in order)
Edit
After reading your comments, here are some lines of code
$input = "string with {LABELS} between brackets {HERE} and {HERE}";
//Extract labels and replace with \0
$tmp=preg_split('/(\{.*?\})/',$input,-1,PREG_SPLIT_DELIM_CAPTURE);
$labels=array();
$txt=array();
$islabel=false;
foreach ($tmp as $t) {
if ($islabel) $labels[]=$t;
else $txt[]=$t;
$islabel=!$islabel;
}
$txt=implode("\0",$txt);
//Run through operate()
$txt=operate($txt);
//Reasssemble
$txt=explode("\0",$txt);
$result='';
foreach ($txt as $t)
$result.=$t.array_shift($labels);
echo $result;
Here's what I would do as a first attempt. Split your string into single words, then feed them into operate() one by one, depending on whether the word is 'braced' or not.
$input = "string with {LABELS} between brackets {HERE} and {HERE}";
$inputArray = explode(' ',$input);
foreach($inputArray as $key => $value) {
if(!preg_match('/^{.*}$/',$value)) {
$inputArray[$key] = operate($value);
}
}
$output = implode(' ',$inputArray);

filter specific string in php

$var="UseCountry=1
UseCountryDefault=1
UseState=1
UseStateDefault=1
UseLocality=1
UseLocalityDefault=1
cantidad_productos=5
expireDays=5
apikey=ABQIAAAAFHktBEXrHnX108wOdzd3aBTupK1kJuoJNBHuh0laPBvYXhjzZxR0qkeXcGC_0Dxf4UMhkR7ZNb04dQ
distancia=15
AutoCoord=1
user_add_locality=0
SaveContactForm=0
ShowVoteRating=0
Listlayout=0
WidthThumbs=100
HeightThumbs=75
WidthImage=640
HeightImage=480
ShowImagesSystem=1
ShowOrderBy=0
ShowOrderByDefault=0
ShowOrderDefault=DESC
SimbolPrice=$
PositionPrice=0
FormatPrice=0
ShowLogoAgent=1
ShowReferenceInList=1
ShowCategoryInList=1
ShowTypeInList=1
ShowAddressInList=1
ShowContactLink=1
ShowMapLink=1
ShowAddShortListLink=1
ShowViewPropertiesAgentLink=1
ThumbsInAccordion=5
WidthThumbsAccordion=100
HeightThumbsAccordion=75
ShowFeaturesInList=1
ShowAllParentCategory=0
AmountPanel=
AmountForRegistered=5
RegisteredAutoPublish=1
AmountForAuthor=5
AmountForEditor=5
AmountForPublisher=5
AmountForManager=5
AmountForAdministrator=5
AutoPublish=1
MailAdminPublish=1
DetailLayout=0
ActivarTabs=0
ActivarDescripcion=1
ActivarDetails=1
ActivarVideo=1
ActivarPanoramica=1
ActivarContactar=1
ContactMailFormat=1
ActivarReservas=1
ActivarMapa=1
ShowImagesSystemDetail=1
WidthThumbsDetail=120
HeightThumbsDetail=90
idCountryDefault=1
idStateDefault=1
ms_country=1
ms_state=1
ms_locality=1
ms_category=1
ms_Subcategory=1
ms_type=1
ms_price=1
ms_bedrooms=1
ms_bathrooms=1
ms_parking=1
ShowTextSearch=1
minprice=
maxprice=
ms_catradius=1
idcatradius1=
idcatradius2=
ShowTotalResult=1
md_country=1
md_state=1
md_locality=1
md_category=1
md_type=1
showComments=0
useComment2=0
useComment3=0
useComment4=0
useComment5=0
AmountMonthsCalendar=3
StartYearCalendar=2009
StartMonthCalendar=1
PeriodOnlyWeeks=0
PeriodAmount=3
PeriodStartDay=1
apikey=ABQIAAAAJ879Hg7OSEKVrRKc2YHjixSmyv5A3ewe40XW2YiIN-ybtu7KLRQiVUIEW3WsL8vOtIeTFIVUXDOAcQ
";
in that string only i want "api==ABQIAAAAJ879Hg7OSEKVrRKc2YHjixSmyv5A3ewe40XW2YiIN-ybtu7KLRQiVUIEW3WsL8vOtIeTFIVUXDOAcQ";
plz guide me correctly;
EDIT
As shamittomar pointed out, the parse_str will not work for this situation, posted the proper regex below.
Given this seems to be a QUERY STRING, use the parse_str() function PHP provides.
UPDATE
If you want to do it with regex using preg_match() as powertieke pointed out:
preg_match('/apikey=(.*)/', $var, $matches);
echo $matches[1];
Should do the trick.
preg_match(); should be right up your alley
people are so fast to jump to preg match when this can be done with regular string functions thats faster.
$string = '
expireDays=5
apikey=ABQIAAAAFHktBEXrHnX108wOdzd3aBTupK1kJuoJNBHuh0laPBvYXhjzZxR0qkeXcGC_0Dxf4UMhkR7ZNb04dQ
distancia=15
AutoCoord=1';
//test to see what type of line break it is and explode by that.
$parts = (strstr($string,"\r\n") ? explode("\r\n",$string) : explode("\n",$string));
$data = array();
foreach($parts as $part)
{
$sub = explode("=",trim($part));
if(!empty($sub[0]) || !empty($sub[1]))
{
$data[$sub[0]] = $sub[1];
}
}
and use $data['apikey'] for your api key, i would also advise you to wrpa in function.
I can bet this is a better way to parse the string and much faster.
function ParsemyString($string)
{
$parts = (strstr($string,"\r\n") ? explode("\r\n",$string) : explode("\n",$string));
$data = array();
foreach($parts as $part)
{
$sub = explode("=",trim($part));
if(!empty($sub[0]) || !empty($sub[1]))
{
$data[$sub[0]] = $sub[1];
}
}
return $data;
}
$data = ParsemyString($string);
First of all, you are not looking for
api==ABQIAAAAJ879Hg7OSEKVrRKc2YHjixSmyv5A3ewe40XW2YiIN-ybtu7KLRQiVUIEW3WsL8vOtIeTFIVUXDOAcQ
but you are looking for
apikey=ABQIAAAAJ879Hg7OSEKVrRKc2YHjixSmyv5A3ewe40XW2YiIN-ybtu7KLRQiVUIEW3WsL8vOtIeTFIVUXDOAcQ
It is important to know if the api-key property always occurs at the end and if the length of the api-key value is always the same. I this is the case you could use the PHP substr() function which would be easiest.
If not you would most probably need a regular expression which you can feed to PHPs preg_match() function. Something along the lines of apikey==[a-zA-Z0-9\-] Which matches an api-key containing a-z in both lowercase and uppercase and also allows for dashes in the key. If you are using the preg_match() function you can retrieve the matches (and thus your api-key value).

Categories