Capitalize last word of a string - php

i have following code which capitalize First name & Last name, But some user have names like : "Malou van Mierlo" or "Malou de Mierlo" i dont want the "van" or "de" to be capital. How do i manage these exceptions? I think i can be solved if i just capitalize the last word in the last name. but how ?
add_filter('woocommerce_checkout_posted_data', 'mg_custom_woocommerce_checkout_posted_data');
function mg_custom_woocommerce_checkout_posted_data($data){
// The data posted by the user comes from the $data param.
// You would look for the fields being posted,
// like "billing_first_name" and "billing_last_name"
if($data['billing_first_name']){
/*
From jAnE to Jane
*/
$data['billing_first_name'] = strtolower($data['billing_first_name']);
$data['billing_first_name'] = ucwords($data['billing_first_name']);
}
if($data['billing_last_name']){
/*
From DOe to Doe
*/
$data['billing_last_name'] = strtolower($data['billing_last_name']);
$data['billing_last_name'] = ucwords($data['billing_last_name']);
}
return $data;
}

You can do it by splitting the string and capitalizing first and last words of the string.
With this code you split the string:
$words = preg_split('/\s+/', $string);
array_map(strtolower, $words); // From jAnE to jane
With this code you capitalize the first and the last words of the name, and return the result:
$words[0] = ucfirst($words[0]);
$words[count($words) - 1] = ucfirst($words[count($words) - 1]);
return implode(' ', $words);

Try this
$a = explode(' ', 'MaLou van mIerlo');
$a[array_key_first($a)] = ucfirst(strtolower($a[array_key_first($a)]));
$a[array_key_last($a)] = ucfirst(strtolower($a[array_key_last($a)]));
$a = implode(' ', $a);

Related

php indexed array manipulation and filtering

I have an array manipulation/situation that I cannot figure out. In a nutshell:
Get a string such as:
$testString = 'John doe 123 Main st 77555';
I am trying to get things split up to be 3 main parts such as:
$fname = 'John';
$lname = 'doe';
$address = '123 Main st 77555';
Currently I am exploding the array as such:
$splitTestString = explode(" ", $testString");
which gives me the string inside an array.
I've tried a for loop to go through the exploded string:
for($i = 0; $i <= count($splitTestString); $i++) {
$fname = $splitTestString[0];
$lname = $splitTestString[1];
if(is_numeric($splitTestString[2])) { //take into account 2 last names
$newAddress = $splitTestString[2];
} else {
$lname .= ' '.$splitTestString[2];
}
}
But I am not sure how to get the address after the initial numbers all into its own variable. Another string example:
$testString = 'John doe smith 123 main st 77555';
$fname = 'John';
$lname = 'doe smith';
$newAddress = '123 main st 77555';
The user would be instructed to enter the information in the above format of first name, last name, address and zip code.
This is my first question out of all the searches I've done on here and please let me know if I've not followed the rules properly. I'm just at my wits end on this problem and cannot seem to find a solution to this situation. Thanks in advance!
You don't need to do everything in a single loop, you should come up with a process for populating the name variables until you hit a word that starts with a number (is this really a safe assumption though?), then simply join the remainder into the address.
If possible, you should go back to the drawing board and provide a way for the user to provide the information in separate fields.
$testString = 'John doe smith villalobos garcia navarro 123 Main st 77555';
$parts = explode(' ', $testString);
// Don't assume we will always have a first or last name, there could be only an address
$fname = '';
// Set up a buffer for the last name words
$lnameBuffer = [];
// Process input buffer until we hit a part that begins with a number
while(!is_numeric(substr($parts[0], 0, 1)))
{
// Shift the next word off of the buffer
$currPart = array_shift($parts);
/*
* If we don't have a first name yet, set it
* Otherwise, append the word to the last name buffer
*/
if(empty($fname))
{
$fname = $currPart;
}
else
{
$lnameBuffer[] = $currPart;
}
}
// Join the last name buffer to populate the $lname variable
$lname = implode(' ', $lnameBuffer);
// The rest of the input buffer contains the address
$newAddress = implode(' ', $parts);
echo 'fname: '.$fname.PHP_EOL;
echo 'lname: '.$lname.PHP_EOL;
echo 'newAddress: '.$newAddress.PHP_EOL;
You could however achieve this much more easily using regex.
$testString = 'John doe smith villalobos garcia navarro 123 Main st 77555';
preg_match('/([^\s]\S+)\s([^\d]*)(.*)/', $testString, $matches);
$fname = $matches[1];
$lname = $matches[2];
$newAddress = $matches[3];
echo 'fname: '.$fname.PHP_EOL;
echo 'lname: '.$lname.PHP_EOL;
echo 'newAddress: '.$newAddress.PHP_EOL;
If your string is always formatted like "firstname lastname everything else is the address" you can just pass explode a limit like so:
$str = 'John doe 123 Main st 77555';
$parts = explode(' ', $str, 3);
var_dump($parts);
//array(3) {
// [0]=>
// string(4) "John"
// [1]=>
// string(3) "doe"
// [2]=>
// string(17) "123 Main st 77555"
//}
If you need to split with a rule like 'the first time we see a number indicates the start of an address' you can just find that and split the string up like so:
$str = 'john doe smith 123 fake street paris france';
$matches = [];
preg_match('/[0-9]/', $str, $matches, PREG_OFFSET_CAPTURE);
$numberPosition = $matches[0][1]; // this is the first matching element, and its position
$left = trim(substr($str, 0, $numberPosition)); // left side of the found number
$right = trim(substr($str, $numberPosition)); // right side of the found number
var_dump([
$left, $right
]);
//array(2) {
// [0]=>
// string(20) "john doe smith"
// [1]=>
// string(26) "123 fake street paris france"
//}

Get the first letter of only first and last name in php

I want to display a user's initials using only the first letter of their first name and the first letter of their last name. (Test User = TU)
How can I achieve this result even if a user inputs a prefix or a middle name? (Mr. Test Middlename User = TU).
This is the code I have so far (but will display more than 2 letters depending on user input):
public function initials() {
$words = explode(" ", $this->name );
$initials = null;
foreach ($words as $w) {
$initials .= $w[0];
}
return strtoupper($initials);
}
There are too many variations, but this should capture the first and last names in a string that may or may not have a prefix or suffix that is terminated with a period:
public function initials() {
preg_match('/(?:\w+\. )?(\w+).*?(\w+)(?: \w+\.)?$/', $this->name, $result);
return strtoupper($result[1][0].$result[2][0]);
}
$result[1] and $result[2] are the first and last capture groups and the [0] index of each of those is the first character of the string.
See an Example
This does a pretty good job, however names with a space in it will only return the second portion, such as De Jesus will only return Jesus. You could add known modifiers for surnames like de, von, van etc. but good luck catching them all, especially since it gets even longer van de, van der, van den.
To extend it for non-English prefixes and suffixes you would probably want to define them and strip them out as some may not end in a period.
$delete = ['array', 'of prefixes', 'and suffixes'];
$name = str_replace($delete, '', $this->name);
//or just beginning ^ and end $
$prefix = ['array', 'of prefixes'];
$suffix = ['array', 'of suffixes'];
$name = preg_replace("/^$prefix|$suffix$/", '', $this->name);
You can use reset() and end() to achieve this
reset() rewinds array's internal pointer to the first element and returns the value of the first array element.
end() advances array's internal pointer to the last element, and returns its value.
public function initials() {
//The strtoupper() function converts a string to uppercase.
$name = strtoupper($this->name);
//prefixes that needs to be removed from the name
$remove = ['.', 'MRS', 'MISS', 'MS', 'MASTER', 'DR', 'MR'];
$nameWithoutPrefix=str_replace($remove," ",$name);
$words = explode(" ", $nameWithoutPrefix);
//this will give you the first word of the $words array , which is the first name
$firtsName = reset($words);
//this will give you the last word of the $words array , which is the last name
$lastName = end($words);
echo substr($firtsName,0,1); // this will echo the first letter of your first name
echo substr($lastName ,0,1); // this will echo the first letter of your last name
}

How can I move chinese characters in a string to the end of string?

I have a string like this now: I want to do the following in PHP:
$string = 'Testing giving dancing 喝 喝 passing 制图 giving 跑步 吃';
I want to move all Chinese characters to the end of the string, and also reversing their current order. Accordingly, Removing the duplicate English words and Return the modified string
Here you go! Check the comments in the code:
<?php
$string = 'Testing giving dancing 喝 喝 passing 制图 giving 跑步 吃';
// split by a space into an array
$explosion = explode(' ', $string);
$normalWords = [];
$chineseWords = [];
// loop through the array
foreach ($explosion as $debris) {
// if not normal alphabet characters
if (!preg_match('#[a-zA-Z]+#', $debris) && !in_array($debris, $chineseWords)) {
// add to chinese words array if not already in the array
$chineseWords[] = $debris;
} elseif (preg_match('#[a-zA-Z]+#', $debris) && !in_array($debris, $normalWords)) {
// add to normal words array if not already in the array
$normalWords[] = $debris;
}
}
// reverse the chinese characters like you wanted
$chineseWords = array_reverse($chineseWords);
// Piece it all back together
$string = implode(' ', $normalWords) . ' ' . implode(' ', $chineseWords);
// and output
echo $string; // Testing giving dancing passing 吃 跑步 制图 喝
See it here! https://3v4l.org/FWQWG

Split string in 2 variables but give one variable 2/3 the words

I want to split a string into 2 variables, but give one variable about 75% of the words from the string and the other variable 25%.
I have this code which splits a paragraph from the database in 2, but now I need to give one part 2/3 the words and the other part 1/3 the words. Is this even possible:
Here's my current code:
$pagetext = mysql_result($result, $i, "column");
$thewordamt = str_word_count($pagetext);
$halfwords = $thewordamt / 2;
function limit_words($string, $word_limit) {
$words = explode(" ", $string);
return implode(" ", array_splice($words, 0, $word_limit));
}
$start = limit_words($pagetext, $halfwords); //first part
$end = str_replace($start, '', $pagetext); //second part
I think this explains itself:
$txt = "I met him on a Monday and my heart stood still
Da do ron-ron-ron, da do ron-ron
Somebody told me that his name was Bill
Da do ron-ron-ron, da do ron-ron";
$parts = daDoRunRun($txt, 0.33);
printf('<p>%s</p><p>%s</p>', $parts['short'], $parts['long']);
function daDoRunRun($txt, $short_part_percentage) {
$split_index = floor(str_word_count($txt)*$short_part_percentage);
$words = explode(' ', $txt);
return [
'short' => join(' ', array_splice($words, 0, $split_index)),
'long' => join(' ', $words)
];
}

PHP replace multiple words

So I want to remove everything but some words. I want to keep for an example "car", "circle" and "roof". But remove everything else in a string.
Let's say the string is "I have a car with red one circle at the roof". I wantr to remove everything but "car", "circle" and "roof".
I know there's this one:
$text = preg_replace('/\bHello\b/', 'NEW', $text);
But I can't figure out how to do it with multiple words. I've done this below, but it does the opposite.
$post = $_POST['text'];
$connectors = array( 'array', 'php', 'css' );
$output = implode(' ', array_diff(explode(' ', $post), $connectors));
echo $output;
<?php
$wordsToKeep = array('car', 'circle', 'roof');
$text = 'I have a car with red one circle at the roof';
$words = explode(' ', $text);
$filteredWords = array_intersect($words, $wordsToKeep);
$filteredString = implode(' ', $filteredWords);
$filteredString would then equal car circle roof.
See http://php.net/manual/en/function.array-intersect.php
I suggest the str_word_count() function:
<?php
$string = "Hello fri3nd, you're
looking good today!
I have a car with red one circle at the roof.
An we can add some more _cool_ stuff :D on the roof";
// words to keep
$wordsKeep = array('car', 'circle', 'roof');
// takes care of most cases like spaces, punctuation, etc.
$wordsAll = str_word_count($string, 2, '\'"0123456789');
// remaining words
$wordsRemaining = array_intersect($wordsAll, $wordsKeep);
// maybe do an array_unique() here if you need
// glue the words back to a string
$result = implode(' ', $wordsRemaining);
var_dump($result);
For the sake of reusability, you can create a function like this:
function selector($text,$selected){
$output=explode(' ',$text);
foreach($output as $word){
if (in_array($word,$selected)){
$out[]= trim($word);
}
}
return $out;
}
You get an array like this:
echo implode(' ',selector($post,$connectors));

Categories