I need some help i have this code that Uppercase the first character of each word in a string with exceptions i need the function to ignore the exception if it's at the beginning of the string:
function ucwordss($str, $exceptions) {
$out = "";
foreach (explode(" ", $str) as $word) {
$out .= (!in_array($word, $exceptions)) ? strtoupper($word{0}) . substr($word, 1) . " " : $word . " ";
}
return rtrim($out);
}
$string = "my cat is going to the vet";
$ignore = array("is", "to", "the");
echo ucwordss($string, $ignore);
// Prints: My Cat is Going to the Vet
this is what im doing:
$string = "my cat is going to the vet";
$ignore = array("my", "is", "to", "the");
echo ucwordss($string, $ignore);
// Prints: my Cat is Going to the Vet
// NEED TO PRINT: My Cat is Going to the Vet
- return rtrim($out);
+ return ucfirst(rtrim($out));
Something like this:
function ucwordss($str, $exceptions) {
$out = "";
foreach (explode(" ", $str) as $key => $word) {
$out .= (!in_array($word, $exceptions) || $key == 0) ? strtoupper($word{0}) . substr($word, 1) . " " : $word . " ";
}
return rtrim($out);
}
Or even easier, before return in your function make strtoupper first letter
Do this really cheaply by just always uppercasing your first word:
function ucword($word){
return strtoupper($word{0}) . substr($word, 1) . " ";
}
function ucwordss($str, $exceptions) {
$out = "";
$words = explode(" ", $str);
$words[0] = ucword($words[0]);
foreach ($words as $word) {
$out .= (!in_array($word, $exceptions)) ? ucword($word) : $word . " ";
}
return rtrim($out);
}
what about you make the first letter in the string upper case so no matter your mix you will still come through
$string = "my cat is going to the vet";
$string = ucfirst($string);
$ignore = array("is", "to", "the");
echo ucwordss($string, $ignore);
this way you first letter of the string will always be upper case
preg_replace_callback() will allow you to express your conditional replacement logic in a loopless and dynamic fashion. Consider this approach that will suitably modify your sample data:
Code: (PHP Demo) (Pattern Demo)
$string = "my cat is going to the vet";
$ignore = array("my", "is", "to", "the");
$pattern = "~^[a-z]+|\b(?|" . implode("|", $ignore) . ")\b(*SKIP)(*FAIL)|[a-z]+~";
echo "$pattern\n---\n";
echo preg_replace_callback($pattern, function($m) {return ucfirst($m[0]);}, $string);
Output:
~^[a-z]+|\b(?|my|is|to|the)\b(*SKIP)(*FAIL)|[a-z]+~
---
My Cat is Going to the Vet
You see, the three piped portions of the pattern (in order) make these demands:
If the start of the string is a word, capitalize the first letter.
If a "whole word" (leveraging the \b word boundary metacharacter) is found in the "blacklist", disqualify the match and keep traversing the input string.
Else capitalize the first letter of every word.
Now, if you want to get particular about contractions and hyphenated words, then you only need to add ' and - to the [a-z] character classes like this: [a-z'-] (Pattern Demo)
If anyone has a fringe cases that will break my snippet (like "words" with special characters that need to be escaped by preg_quote()), you can offer them and I can offer a patch, but my original solution will adequately serve the posted question.
Related
I have this code:
$words = ['mleko', 'masło'];
$words = explode(' ', $value); // create an array of words
foreach($words as $word) { //iterate through words
$word = preg_replace('/[^\w]/uis', '', $word);
if (in_array(mb_strtolower($word), $allergens)) {
$return .= "<b>" . $word . "</b> ";
} else {
$return .= $word . " ";
}
}
The above code works fine, but it deletes characters like:,. e.t.c.
How can I fix it? :)
Problem jest w podejściu jakie zastosowałeś. Nie tylko w linii
$word = preg_replace('/[^\w]/uis', '', $word);
which should be extended with the characters of the Polish alphabet (the range of the \w class is [a-zA-Z0-9_], remember to mention the range of lowercase and uppercase characters separately) like in this line
$word = preg_replace('/[^\wąćęłńóśźżĄĆĘŁŃÓŚŹŻ]/uis', '', $word);
Moreover, I believe that the above line is used incorrectly. In my opinion, you should save the result of this operation in another variable as below
$rawWord = preg_replace('/[^\wąćęłńóśźżĄĆĘŁŃÓŚŹŻ]/uis', '', $word);
Thanks to this, you have access to both the purified and the original value, which you can use in this way
if (in_array(mb_strtolower($rawWord), $allergens)) {
$return .= str_replace($rawWord, "<b>{$rawWord}</b> ", $word);
} else {
$return .= $word;
}
With this approach, however, you will still miss some characters. Even spaces that you filtered out with explode earlier. In my opinion, instead of concatenating a string, you should build an array and finally concatenate it with spaces. Complete code below.
$allergens = ['jogurt', 'jaja', 'żytni', "jogurt", "banan"];
$value = 'Chleb żytni, masło z mleka, jogurt naturalny z mleka, jaja, pieczeń rzymska z kaszą gryczaną.';
$returns = [];
$words = explode(' ', $value); // create an array of words
foreach($words as $word) { //iterate through words
$rawWord = preg_replace('/[^\wąćęłńóśźżĄĆĘŁŃÓŚŹŻ]/uis', '', $word);
if (in_array(mb_strtolower($rawWord), $allergens)) {
$returns[] = str_replace($rawWord, "<b>{$rawWord}</b>", $word);
} else {
$returns[] = $word;
}
}
$return = implode(' ', $returns);
Look at this line
$returns[] = str_replace($rawWord, "<b>{$rawWord}</b>", $word);
Replaces the original word (containing the characters you want to ignore) with cleaned and bold version of the word. This keeps all characters (like commas) stuck to the word.
In the $return variable at the end you will get something like this
Chleb żytni, masło z mleka, jogurt naturalny z mleka, jaja, pieczeń rzymska z kaszą gryczaną.
I am trying to check if word is occur in a string but not to be the first and last word, if its true then remove the space after and before of the word and replace with a underscore.
Input:
$str = 'This is a cool area";
Output:
$str = 'This is a_cool_area";
I want to check that the word 'cool' is inside the string but not a first and last word. if yes the remove the space & replace with '_'
You can use preg_replace to do this job, using this regex:
/(?<=\w)\s+(' . $word . ')\s+(?=\w)/i
which looks for the word, surrounded by at least one word character on either side (to prevent matching at the beginning or ending of the sentence). Usage in PHP:
$str = 'This is a cool area';
$word = 'cool';
$str = preg_replace('/(?<=\w)\s+(' . $word . ')\s+(?=\w)/i', '_$1_', $str);
echo $str . "\n";
$str = ' Cool areas are cool ';
$str = preg_replace('/(?<=\w)\s+(' . $word . ')\s+(?=\w)/i', '_$1_', $str);
echo $str . "\n";
Output:
This is a_cool_area
Cool areas are cool
Demo on 3v4l.org
function checkWord($str, $word)
{
$arr = explode(" ", $str);
$newArr = array_slice($arr, 1, -1);
$key = array_search($word, $newArr);
if($key !== false)
{
return implode('_',array_slice($arr, $key, 3));
}
else
{
return $str;
}
}
echo checkWord('This is a cool area', 'cool');
I am trying to reverse a string containing Hebrew from RTL to LTR, but my coding attempt is reversing brackets as well. strrev() didn't work because it does not actually work for UTF8 strings. So I wrote a custom function, below is my code:
$str = 'תירס גדול A-10 (פרי גליל)';
function utf8_strrev($str)
{
$arr = '';
$words = explode(" ", $str);
$start_tag = '(';
$end_tag = ')';
foreach ($words as $word)
{
if (preg_match("/\p{Hebrew}/u", $word))
{
preg_match_all('/./us', $word, $ar);
echo print_r($ar[0]);
echo '<br>';
$arr = join('', array_reverse($ar[0])) . " " . $arr;
} else
{
preg_match_all('/./us', $word, $ar);
$arr = join('', $ar[0]) . " " . $arr;
}
}
return $arr;
}
OUTPUT :
)לילג ירפ( A-10 לודג סרית
what it should be:
(לילג ירפ) A-10 לודג סרית
Found this function in the comments on the docs that KoenHoeijmakers posted. I tested it, but I don't read Hebrew so it is hard for me to tell if it's working correctly.
function utf8_strrev($str){
preg_match_all('/./us', $str, $ar);
return join('',array_reverse($ar[0]));
}
Edit
Based on reading your question again, I think this works as you need it to?
function utf8_strrev($str)
{
$arr = '';
$words = explode(" ", $str);
$start_tag = '(';
$end_tag = ')';
foreach ($words as $word)
{
if (preg_match("/\p{Hebrew}/u", $word))
{
preg_match_all('/./us', $word, $ar);
$arr = join('', array_reverse($ar[0])) . " " . $arr;
} else
{
preg_match_all('/./us', $word, $ar);
$arr = join('', $ar[0]) . " " . $arr;
}
}
return preg_replace(array('/\)(.)/','/(.)\(/','/\}(.)/','/(.)\{/'),array('($1','$1)','{$1','$1}'),$arr);
}
$str='תירס גדול A-10 {פרי גליל}';
echo utf8_strrev($str);
Outut
{לילג ירפ} A-10 לודג סרית
Again, I don't read Hebrew, but hopefully it answers your question.
Note The reason I used preg_replace instead of str_replace is because the string replace method was giving me issues text like ( somthing something ( or ) something something )
I don't speak/read Hebrew, but this seems to work as desired.
I generally dislike nesting preg_ calls inside preg_ calls, but in this case, splitting the unicode characters into an array then reversing the elements prevents the need to bother with mb_encodings.
Code: (Demo)
$str = 'תירס גדול A-10 (פרי גליל)';
echo preg_replace_callback(
"/\p{Hebrew}+(?: \p{Hebrew}+)*/u",
fn($m) => implode(
array_reverse(
preg_split('~~u', $m[0], 0, PREG_SPLIT_NO_EMPTY)
)
),
$str
);
Output:
סרית A-10 (לילג ירפ)
The preg_replace_callback() pattern isolates consecutive space-delimited Hebrew words, then the anonymous function splits the multibyte letters into individual array elements, before reversing their order and joining the elements back into a single mutated string.
In JS you can do:
var chs = "[](){}";
var str = "hello[asd]}";
if (str.indexOf(chs) != -1) {
alert("The string can't contain the following characters: " + chs.split("").join(", "));
}
How can you do this in PHP (replacing alert with echo)?
I do not want to use a regex for the simplicity of what I think.
EDIT:
What I've tried:
<?php
$chs = /[\[\]\(\)\{\}]/;
$str = "hella[asd]}";
if (preg_match(chs, str)) {
echo ("The string can't contain the following characters: " . $chs);
}
?>
Which obviously doesn't work and idk how to do it without regex.
In php you should do this:
$string = "Sometring[inside]";
if(preg_match("/(?:\[|\]|\(|\)|\{|\})+/", $string) === FALSE)
{
echo "it does not contain.";
}
else
{
echo "it contains";
}
The regex says check to see any of the characters are inside the string. you can read more about it here:
http://en.wikipedia.org/wiki/Regular_expression
And about PHP preg_match() :
http://php.net/manual/en/function.preg-match.php
Update:
I have written an updated regex for this, which captures the letters inside:
$rule = "/(?:(?:\[([\s\da-zA-Z]+)\])|\{([\d\sa-zA-Z]+)\})|\(([\d\sa-zA-Z]+)\)+/"
$matches = array();
if(preg_match($rule, $string, $matches) === true)
{
echo "It contains: " . $matches[0];
}
It returnes something like this:
It contains: [inside]
I have changed the regex only which becomes:
$rule = "/(?:(?:(\[)(?:[\s\da-zA-Z]+)(\]))|(\{)(?:[\d\sa-zA-Z]+)(\}))|(\()(?:[\d\sa-zA-Z]+)(\))+/";
// it returns an array of occurred illegal characters
It now returns [] for this "I am [good]"
Why not you try str_replace.
<?php
$search = array('[',']','{','}','(',')');
$replace = array('');
$content = 'hella[asd]}';
echo str_replace($search, $replace, $content);
//Output => hellaasd
?>
Instead of regex we can use string replace for this case.
here is a simple solution without using regex:
$chs = array("[", "]", "(", ")", "{", "}");
$string = "hello[asd]}";
$err = array();
foreach($chs AS $key => $val)
{
if(strpos($string, $val) !== false) $err[]= $val;
}
if(count($err) > 0)
{
echo "The string can't contain the following characters: " . implode(", ", $err);
}
How can I make upper-case the first character of each word in a string accept a couple of words which I don't want to transform them, like - and, to, etc?
For instance, I want this - ucwords('art and design') to output the string below,
'Art and Design'
is it possible to be like - strip_tags($text, '<p><a>') which we allow and in the string?
or I should use something else? please advise!
thanks.
None of these are really UTF8 friendly, so here's one that works flawlessly (so far)
function titleCase($string, $delimiters = array(" ", "-", ".", "'", "O'", "Mc"), $exceptions = array("and", "to", "of", "das", "dos", "I", "II", "III", "IV", "V", "VI"))
{
/*
* Exceptions in lower case are words you don't want converted
* Exceptions all in upper case are any words you don't want converted to title case
* but should be converted to upper case, e.g.:
* king henry viii or king henry Viii should be King Henry VIII
*/
$string = mb_convert_case($string, MB_CASE_TITLE, "UTF-8");
foreach ($delimiters as $dlnr => $delimiter) {
$words = explode($delimiter, $string);
$newwords = array();
foreach ($words as $wordnr => $word) {
if (in_array(mb_strtoupper($word, "UTF-8"), $exceptions)) {
// check exceptions list for any words that should be in upper case
$word = mb_strtoupper($word, "UTF-8");
} elseif (in_array(mb_strtolower($word, "UTF-8"), $exceptions)) {
// check exceptions list for any words that should be in upper case
$word = mb_strtolower($word, "UTF-8");
} elseif (!in_array($word, $exceptions)) {
// convert to uppercase (non-utf8 only)
$word = ucfirst($word);
}
array_push($newwords, $word);
}
$string = join($delimiter, $newwords);
}//foreach
return $string;
}
Usage:
$s = 'SÃO JOÃO DOS SANTOS';
$v = titleCase($s); // 'São João dos Santos'
since we all love regexps, an alternative, that also works with interpunction (unlike the explode(" ",...) solution)
$newString = preg_replace_callback("/[a-zA-Z]+/",'ucfirst_some',$string);
function ucfirst_some($match)
{
$exclude = array('and','not');
if ( in_array(strtolower($match[0]),$exclude) ) return $match[0];
return ucfirst($match[0]);
}
edit added strtolower(), or "Not" would remain "Not".
How about this ?
$string = str_replace(' And ', ' and ', ucwords($string));
You will have to use ucfirst and loop through every word, checking e.g. an array of exceptions for each one.
Something like the following:
$exclude = array('and', 'not');
$words = explode(' ', $string);
foreach($words as $key => $word) {
if(in_array($word, $exclude)) {
continue;
}
$words[$key] = ucfirst($word);
}
$newString = implode(' ', $words);
I know it is a few years after the question, but I was looking for an answer to the insuring proper English in the titles of a CMS I am programming and wrote a light weight function from the ideas on this page so I thought I would share it:
function makeTitle($title){
$str = ucwords($title);
$exclude = 'a,an,the,for,and,nor,but,or,yet,so,such,as,at,around,by,after,along,for,from,of,on,to,with,without';
$excluded = explode(",",$exclude);
foreach($excluded as $noCap){$str = str_replace(ucwords($noCap),strtolower($noCap),$str);}
return ucfirst($str);
}
The excluded list was found at:
http://www.superheronation.com/2011/08/16/words-that-should-not-be-capitalized-in-titles/
USAGE: makeTitle($title);