Regular Expression to find last name in "Firstname Lastname, Credentials" format - php

I am trying to find the last name from full names with trailing credentials. Some names have middle names or initials, hyphenated names, multiple credentials, and some have no trailing credentials:
John Doe, MD
Jane X. Doe, FNP-C
Joe Cool, MD, PhD
Billie-Jo Last
I've started with
/\w+(?=[\s,]+\S*$)/gmi
which gets the last names of the first 2 formattings, but picks up the 1st credential and first name of the second 2 formattings, respectively.
Thank you for all your help.

If you are 100% confident that they all follow the format you posted, you can do this per row (per person):
// Get the names part of the string
$parts = exlode(',', $nameString);
// The first element is the names.
// Now, split the name string to get the names
$names = explode(' ', $parts[0]);
$first = $names[0];
$middle = null;
$last = null;
if (count($names) == 2) {
// We only have two names, which probably means that
// the second is the last name
$last = $names[1];
}
if (count($names) == 3) {
// We got three names, let's assume that the second is the middle name
$middle = $names[1];
// And the third is the last name
$last = $names[2];
}
The above code can be optimized, but I wanted to make it as self explanatory as possible.
Note: This only works for the names that follows the format you mentioned. If you were to get more than three names, you have a problem since you won't be able to determine if it is a double first, middle or last name.

If all your input is well structured as you described, then the best advice is to do what #Magnus Eriksson stated in his commend. The code is extremely simple:
$parts = explode(',', $inputString);
$names = explode(' ', trim($parts[0]));
$lastName = $names[count($names) - 1];

Related

ucwords(strtolower()) not working together php

I have code where I am extracting a name from a database, trying to reorder the word, and then changing it from all uppercase to word case. Everything I find online suggests my code should work, but it does not... Here is my code and the output:
$subjectnameraw = "SMITH, JOHN LEE";
$subjectlname = substr($subjectnameraw, 0, strpos($subjectnameraw, ",")); // Get the last name
$subjectfname = substr($subjectnameraw, strpos($subjectnameraw, ",") + 1) . " "; // Get first name and middle name
$subjectname = ucwords(strtolower($subjectfname . $subjectlname)); // Reorder the name and make it lower case / upper word case
However, the output looks like this:
John Lee smith
The last name is ALWAYS lowercase no matter what I do. How can I get the last name to be uppercase as well?
The above code gives wrong results when there are multibyte characters in the names like RENÉ. The following solution uses the multibyte function mb_convert_case.
$subjectnameraw = "SMITH, JOHN LEE RENÉ";
list($lastName,$firstnName) = explode(', ',mb_convert_case($subjectnameraw,MB_CASE_TITLE,'UTF-8'));
echo $firstnName." ".$lastName;
Demo : https://3v4l.org/ekTQA

Explode surname and name by lower/upper

How can I separate firstname and surname from a string like this:
Pietro DE GIOVANNI
(Pietro being the firstname and DE GIOVANNI the surname)
I used to do it with an explode() on the spaces, but obviously it doesn't work on a person like that.
Thanks in advance.
You can explode on the names by spaces as before, then loop the result as individual pieces of the name. Check with ctype_upper() if the string is purely uppercase or not, and append it to the proper variable.
Putting it into a function, it may look like this
function split_name($fullname) {
$firstname = "";
$surname = "";
$pieces = explode(" ", $fullname);
foreach ($pieces as $name) {
if (ctype_upper($name))
$surname .= $name." ";
else
$firstname .= $name. " ";
}
return array("firstname" => $firstname, "surname" => $surname);
}
You can then use it as such
$name = "Pietro DE GIOVANNI";
$split = split_name($name);
echo "Firstname: ".$split['firstname']."\nSurname: ".$split['surname'];
Note
This doesn't work for names such as James O'RILEY, John-Paul JOHNSON or John. F. KENNEDY. The first two we can circumvent by stripping away any characters that's not a-zA-Z before comparing with ctype_upper(), but the latter we won't be able to distinguish if it's a firstname or surname - there's not enough data to say either way. You can assume that it's always a part of the firstname (for instance), and/or check if it's after we've started looking at the surnames (if a name in capital letters has been found yet). You can take care of the first two cases by checking for
if (ctype_upper(filter_var(str_replace("'", "", $name), FILTER_SANITIZE_STRING)))
instead of using the if statement in the original codeblock. This removes quotes and any non-a-zA-Z values.
Here's a live demo where I've stripped away names that contain any characters beside a-zA-Z, which would account for the two first issues.

How to Search for Space in Php String?

I'd like to know How to Search for Space in Php
For example , I've got $Studentname and it's value is John Green . I want to have $Name (with value John) And $Surname(With value Green) . But i don't know how to search space in string .
Thanks in advance
Using explode() without a limit will result in incorrect results. Some first and last names have spaces. For example:
$name = explode(" ","Jan Van Riebeck");
echo $name[0]." ".$name[1]; // Jan Van (incorrect)
$name = explode(" ","St. John Westcox");
echo $name[0]." ".$name[1]; // St. John (incorrect)
Use explode() with a limit (so it only returns 2 items), like so:
$name = explode(" ","Jan Van Riebeck",2);
echo $name[0]." ".$name[1]; // Jan Van Riebeck (correct)
This will still be incorrect some time, but more last names have spaces than first names. Ideally, if you're capturing the form data, use two different fields for first and last name, but even this isn't always ideal, some cultures have different ways that names work that aren't as simple as first name last name.
Here is a list of common pitfalls when it comes to working with names
First suggestion:-
Try to take first name and last name in two different fields when you are using html form.
Use below code if the above not possible:-
<?php
$Studentname = 'John Green';
$student_full_name = explode(' ',trim($Studentname));//trim to remove space from starting and ending and explode to break string when space found
$first_name = $student_full_name[0];//output John
$sur_name = $student_full_name[1];//output Green
?>
Note:- What happen if a user put name like "John Green smith" Or "John(more than one space)Green". That's why do first point.
You can use the explode() function to split a string into an array by using the space as a delimiter:
$names = explode(" ", "John Smith");
However, you might want to take account of people doing silly things like putting double spaces between the first name and last name, or having preceding or trailing spaces.
You can use trim() for getting rid of trailing and preceding spaces:
$fullName = " John Smith ";
$trimmedName = trim($fullName); // Assigns "John Smith"
You can also use preg_replace() to get rid of multiple spaces between the first and last name:
$fullName = "John Smith";
$cleanedName = preg_replace("/\s+/", " ", $fullName); // Assigns "John Smith"
The above code will replace one or more (+) consecutive spaces (\s) with a single space.
to get name and username from student name follow this
$Studentname = 'John Green';
$name = explode(' ',$Studentname);
$firstname = $name[0]; //output john
$lastname = $name[1]; //output green

PHP: Filtering and posting a text file

I have a text file that contains a persons surname, address, time of accident and reason of accident separated by a white space in a line. I need to filter this file by only the people that have called in at least two times for the same reason and echo it.
I'm fairly new to PHP so I would like a simple way. :)
Thank you.
EDIT:
I haven't tried anything since I have no clue how to even filter file contents.
$data = array($_POST['surname'], $_POST['address'], $_POST['time'], $_POST['reason']);
$info = implode(" ", $data)
$info .= "\r\n";
serialize($info);
file_put_contents("data.txt", $info, FILE_APPEND);
serialize($info);
This is how I wrote it into a file.
I imploded the file because I needed to make them separated by 3 white spaces, but it no longer matters so I can just keep the array.
The expected output should be something like this:
Surname Address Time Reason
Adams Railroad 5 13:20 Heart Attack
Adams Railroad 5 23:35 Heart Attack
It would only need to repeat the same people that have matching Surnames and Reasons.
Update
your text file contains string, entries seprated by line brakes and values by three spaces (actually html coded spaces).
Here we read whole txt file in,(some could do this line by line):
$whole_string = file_get_contents('data.txt');
So firstly we get each line:
$entries = explode('\n',$whole_string);
Then value arrays are pushed:
$whole_ar = array();
foreach($entries as $e){
$whole_ar[] = explode(' ',$e);
}//if 3 spaces in file are in html
We get:
array(
array(
'name','date','etc..'
),
array(
'name2','date','etc..'
),
array(
'name2','date','etc..'
)
)
You could store array in php file, for later to include('data.php'); like so:
$file = '<?php $whole_ar='.var_export($whole_ar, TRUE)."; ?>";
file_put_contents('data.php', $file);
Main answer on how to parse this array to target copies is iteritating or:
$answer = array_unique(array_diff_assoc($whole_ar, array_unique( $whole_ar)));
As I understand, you get information like this string when user calls in:
$newest = "Huchinson Estonia Tallin Geo street 13 2015.12.02 13:44 Gas leak"
You have this string in variable, like stated above.
Then you could explode string by space characters: $data = explode(" ",$newest); which gives you an array with number of values. First value will be a surname and last will be reason of accident.
Parse them out of array like this: echo $data[0];//this will be surname and echo end($data);//this will be accident type
Instead of echo you can assign these values to variables and look up if this surname AND accident is present in your database:
if($saved_before == $data[0].end($data)){
echo "we are working on ".end($data).", be patient, dear ".$data[0];
}
p.s. dot (.) is for concatenating strings
If i understand well the txt file is a csv file that uses a space as the delimenter of the columns. So use use fgetcsv function to load columns of each row. Specify the blank space as the delimiter.
That should get you started:
function parseIt($line) { return str_getcsv($line, " "); }
$all = array_map('parseIt', file('yourfile.txt'));
$names = array();
foreach ($all as $row) {
$uniqkey = $row[0].$row[3];
if (isset($names[$uniqkey])) {
echo implode(" ",$row);
$names[$uniqkey]++;
} else {
$names[$uniqkey] = 1;
}
}
I noticed in your file writing code you use a delimiter of 3 white spaces so I used it in the example - you can set it to whatever you want in the str_getcsv(line, delimiter)
Explanation:
Lines 1,2 - file() will read the file into an array that are passed through the function parseIt() this function will parse the line and return an array of the line value.
Line 3 - The array $names will act our memory, at the end it will hold all names + reason as keys and the value will be the counter of occurrences.
Line 4... - Loops through $all checks if the key exists in $names if it does it prints the row and moves the counter otherwise sets a new key in $names and set its value to 1 (counter).

Remove equal part of two strings

In PHP, I have two paths on a server that both have a matching part. I'd like to join them, but delete the part that is equal.
EXAMPLE:
Path #1:
/home7/username/public_html/dir/anotherdir/wp-content/uploads
Path #2:
/dir/anotherdir/wp-content/uploads/2011/09/image.jpg
You see the part /dir/anotherdir/wp-content/uploads is the same in both strings, but when I simply join them I would have some directories twice.
The output I need is this:
/home7/username/public_html/dir/anotherdir/wp-content/uploads/2011/09/image.jpg
Since the dirs can change on different servers I need a dynamic solution that detects the matching part from #2 and removes it on #1 so I can trail #2 right after #1 :)
$path1 = "/home7/username/public_html/dir/anotherdir/wp-content/uploads";
$path2 = "/dir/anotherdir/wp-content/uploads/2011/09/image.jpg";
echo $path1 . substr($path2, strpos($path2, basename($path1)) + strlen(basename($path1)));
The problem is not so generic here. You should not look at the problem as matching equal parts of strings, rather you should look at it like equal directory structure.
That said you need to concentrate on strings after '/'.
So basically you need to do string matching of directory names. Moreover your problem looks like that first input file name's last part of directory structure name may be common to some part (starting from first character) of second input string.
So I will suggest to start reading the first input from end at the jumps of '/' and try to get first string matching with the first folder name in second file-path. If match happens then rest of the string character from this index to last index in first file-path should be there in first part of second input string. If this condition fails the repeat the process of finding the first directory name in second string matching with a directory name in first file-name for next index.
This code can help you:
$str1 = $argv[1];
$str2 = $argv[2];
//clean
$str1 = trim(str_replace("//", "/", $str1), "/");
$str2 = trim(str_replace("//", "/", $str2), "/");
$paths1 = explode("/", $str1);
$paths2 = explode("/", $str2);
$j = 0;
$found = false;
$output = '';
for ($i=0; $i<count($paths1); $i++) {
$item1 = $paths1[$i];
$item2 = $paths2[$j];
if ($item1 == $item2) {
if (!$found)
$found = $i; //first point
$j++;
} else if ($found) {
//we have found a subdir so remove
$output = "/".implode("/", array_slice($paths1, 0, $i))
."/".implode("/", array_slice($paths2, $j));
$found = false;
break;
}
}
//final checking
if ($found) {
$output = "/".implode("/", $paths1)
."/".implode("/", array_slice($paths2, $j));
}
print "FOUND?: ".(!empty($output)?$output:'No')."\n";
Will detect the equal substrings and will cut the first string until that point and copy the other part from second string.
This code will accept also two strings if they share "partial" substrings like:
/path1/path2/path3
/path2/other/file.png
will output:
/path/path2/other/file.png
And will remove the "path3", but with few changes can be more strict
how about using the similar_text as described in this link. It returns the matching chars between two strings. Once you have it, replace the first one with empty string and append the second.

Categories