27

ok so basically I am asking the question of their name I want this to be one input rather than Forename and Surname.

Now is there any way of splitting this name? and taking just the last word from the "Sentence" e.g.

name = "Thomas Winter"
print name.split() 

and what would be output is just "Winter"

S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • 4
    Here's the obligatory "Stuff every programmer should know" article: https://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/ – tripleee Sep 19 '18 at 10:36
  • See also https://stackoverflow.com/questions/1122328/first-name-middle-name-last-name-why-not-full-name – Raedwald Oct 01 '19 at 10:37

18 Answers18

67

You'll find that your key problem with this approach isn't a technical one, but a human one - different people write their names in different ways.

In fact, the terminology of "forename" and "surname" is itself flawed.

While many blended families use a hyphenated family name, such as Smith-Jones, there are some who just use both names separately, "Smith Jones" where both names are the family name.

Many european family names have multiple parts, such as "de Vere" and "van den Neiulaar". Sometimes these extras have important family history - for example, a prefix awarded by a king hundreds of years ago.

Side issue: I've capitalised these correctly for the people I'm referencing - "de" and "van den" don't get captial letters for some families, but do for others.

Conversely, many Asian cultures put the family name first, because the family is considered more important than the individual.

Last point - some people place great store in being "Junior" or "Senior" or "III" - and your code shouldn't treat those as the family name.

Also noting that there are a fair number of people who use a name that isn't the one bestowed by their parents, I've used the following scheme with some success:

Full Name (as normally written for addressing mail); Family Name; Known As (the name commonly used in conversation).

e.g:

Full Name: William Gates III; Family Name: Gates; Known As: Bill

Full Name: Soong Li; Family Name: Soong; Known As: Lisa

Bevan
  • 43,618
  • 10
  • 81
  • 133
  • 1
    +1. For applications, I usually have a "full name" and "nickname" fields, that are populated independently. I haven't had a use case for "family name", but YMMV. – erickson Nov 03 '08 at 20:28
  • 2
    +1 - PLEASE don't forget those of us blessed by our parents to use a name other than our First name - Like 'J. Edgar Hoover'. Legal Name (and CC, most times) requires 'J. Edgar Hoover'; Casual/Nickname/Known-As would be 'Edgar Hoover'. First Name, MI, Last Name don't cut it. – Ken Gentle Nov 03 '08 at 21:02
  • 4
    And some people don't have a "surname" or a "family name", e.g. in some East African cultures, they use father's name and grandfather's name e.g. Tom Dick Harry. In some cases the family nameS are in the middle e.g. Anson Maria Elizabeth Chan Fong On-sang. See also the the Wikipedia articles "Icelandic name", "Arabic name" and "Names in the Russian Empire, Soviet Union and CIS countries". – John Machin Nov 01 '09 at 11:13
  • Great write up. Thanks. I think @xeolot's post about python-nameparser takes a great stab at everything you mentioned. – dlink Feb 15 '18 at 21:10
16

The problem with trying to split the names from a single input is that you won't get the full surname for people with spaces in their surname, and I don't believe you'll be able to write code to manage that completely.

I would recommend that you ask for the names separately if it is at all possible.

Dave DuPlantis
  • 6,378
  • 3
  • 26
  • 30
  • Agreed, what about say, Mike St. James for example? An incorrect surname would be returned. – Fry Nov 03 '08 at 19:27
  • Anne Marie van Guido. Where does the firstname stop and the last name begin?! The humanity! – Tom Ritter Nov 03 '08 at 19:29
  • Not to mention cultures where the family name is given first. Asking for the name at once is OK only so long as you always treat it as a single unit. Trying to split it will generally result in mangling some cases. – Brian Nov 03 '08 at 19:43
  • Some names also have an apostrophe or other special characters which cause problems if not handled correctly. A lot of Irish names, e.g. O'Connor, fall into this category. – Ryan Nov 03 '08 at 20:26
  • As a person who has multiple surnames, I'm getting a kick of these answers... ;-) – cethegeek Nov 01 '09 at 03:02
  • @Ryan: or they don't have an apostrophe, e.g. "Gearóid Ó Súilleabháin" ... for whom you may have a duplicate database record filed under "Gerard O'Sullivan" :-) – John Machin Nov 01 '09 at 10:00
16

This is a pretty old issue but I found it searching around for a solution to parsing out pieces from a globbed together name.

http://code.google.com/p/python-nameparser/

Xealot
  • 1,659
  • 14
  • 26
  • 3
    It's very USA-centric (e.g. the titles appear to cover just about every rank in the US armed forces) and the capitalisation code produces the usual nonsenses like MacE and MacK and MacHin :-( – John Machin May 19 '10 at 04:02
  • I think this is a great python library that takes a full shot at dealing with all the issues @bevan listed in his post. Granted JohnMachin's comments about it being USA centric, however that's OK for my use case. I started writing a simpler version of python-nameparser, before I read your post. Thanks. – dlink Feb 15 '18 at 21:09
9

An easy way to do exactly what you asked in python is

name = "Thomas Winter"
LastName = name.split()[1]

(note the parantheses on the function call split.)

split() creates a list where each element is from your original string, delimited by whitespace. You can now grab the second element using name.split()[1] or the last element using name.split()[-1]

However, as others said, unless you're SURE you're just getting a string like "First_Name Last_Name", there are a lot more issues involved.

Baltimark
  • 9,052
  • 12
  • 37
  • 35
  • If you are looking for just FirstName as well its: FirstName = name.split()[0] -- But this is what I was looking for (barring any middle name's :) ). Thanks! – hiquetj Mar 22 '18 at 23:48
6

Golden rule of data - don't aggregate too early - it is much easier to glue fields together than separate them. Most people also have a middle name which should be an optional field. Some people have a plethora of middle names. Some people only have one name, one word. Some cultures commonly have a dictionary of middle names, paying homage to the family tree back to the Golgafrincham Ark landing.

You don't need a code solution here - you need a business rule.

CAD bloke
  • 8,578
  • 7
  • 65
  • 114
4

If you're trying to parse apart a human name in PHP, I recomment Keith Beckman's nameparse.php script.

Jonathon Hill
  • 3,445
  • 1
  • 33
  • 31
4

Like this:

print name.split()[-1]
JesperE
  • 63,317
  • 21
  • 138
  • 197
4

This is how I do it in my application:

def get_first_name(fullname):
    firstname = ''
    try:
        firstname = fullname.split()[0] 
    except Exception as e:
        print str(e)
    return firstname

def get_last_name(fullname):
    lastname = ''
    try:
        index=0
        for part in fullname.split():
            if index > 0:
                if index > 1:
                    lastname += ' ' 
                lastname +=  part
            index += 1
    except Exception as e:
            print str(e)
    return lastname

def get_last_word(string):
    return string.split()[-1]

print get_first_name('Jim Van Loon')
print get_last_name('Jim Van Loon')
print get_last_word('Jim Van Loon')
Ryan Flores
  • 215
  • 4
  • 5
  • Hi. Thanks for the code. Observation: you could eliminate the need to set index with enumerate - for index, part in enumerate(fullname.split()). Also you can eliminate the need for the conditional around += ' ', by using join. lastname = ' '.join(lastnames) – dlink Feb 15 '18 at 20:56
  • `return " ".join(fullname.split()[1:])` instead of everything in `try...except`. – Vedran Šego Feb 25 '18 at 21:58
3

Since there are so many different variation's of how people write their names, but here's how a basic way to get the first/lastname via regex.

import re
p = re.compile(r'^(\s+)?(Mr(\.)?|Mrs(\.)?)?(?P<FIRST_NAME>.+)(\s+)(?P<LAST_NAME>.+)$', re.IGNORECASE)
m = p.match('Mr. Dingo Bat')
if(m != None):
  first_name = m.group('FIRST_NAME')
  last_name = m.group('LAST_NAME')
UberJumper
  • 20,245
  • 19
  • 69
  • 87
  • This code is the shortest and nice one for a casual use. I'm using it with Firebase because Firebase API only gives me full name. One issue is, it doesn't handle `LAST, FIRST`. This can be handled easily by checking for comma before applying this. If there is a comma, then just reverse the regex. – John Pang Sep 03 '18 at 09:28
2

Splitting names is harder than it looks. Some names have two word last names; some people will enter a first, middle, and last name; some names have two work first names. The more reliable (or least unreliable) way to handle names is to always capture first and last name in separate fields. Of course this raises its own issues, like how to handle people with only one name, making sure it works for users that have a different ordering of name parts.

Names are hard, handle with care.

acrosman
  • 12,814
  • 10
  • 39
  • 55
1

It's definitely a more complicated task than it appears on the surface. I wrote up some of the challenges as well as my algorithm for solving it on my blog. Be sure to check out my Google Code project for it if you want the latest version in PHP:

http://www.onlineaspect.com/2009/08/17/splitting-names/

Josh Fraser
  • 863
  • 1
  • 9
  • 10
1

You can use str.find() for this.

x=input("enter your name ")
l=x.find(" ")
print("your first name is",x[:l])
print("your last name is",x[l:])
Nicolas Gervais
  • 33,817
  • 13
  • 115
  • 143
  • 1
    From Review: Please add a description to your answer, and also properly format it.See: [ANSWER](https://stackoverflow.com/help/how-to-answer) – sɐunıɔןɐqɐp Dec 10 '19 at 17:34
0

You would probably want to use rsplit for this:

rsplit([sep [,maxsplit]])

Return a list of the words in the string, using sep as the delimiter string. If maxsplit is given, at most maxsplit splits are done, the rightmost ones. If sep is not specified or None, any whitespace string is a separator. Except for splitting from the right, rsplit() behaves like split() which is described in detail below. New in version 2.4.

dspencer
  • 4,297
  • 4
  • 22
  • 43
Adam Alexander
  • 15,132
  • 5
  • 42
  • 41
0

Here's how to do it in SQL. But data normalization with this kind of thing is really a bear. I agree with Dave DuPlantis about asking for separate inputs.

Community
  • 1
  • 1
JosephStyons
  • 57,317
  • 63
  • 160
  • 234
0

I would specify a standard format (some forms use them), such as "Please write your name in First name, Surname form".

It makes it easier for you, as names don't usually contain a comma. It also verifies that your users actually enter both first name and surname.

Bogdan
  • 3,055
  • 1
  • 22
  • 20
0
name = "Thomas Winter"
first, last = name.split()
print("First = {first}".format(first=first))
#First = Thomas
print("Last = {last}".format(last=" ".join(last)))
#Last = Winter
Zoe
  • 27,060
  • 21
  • 118
  • 148
Kurtis Pykes
  • 301
  • 3
  • 14
  • There are some issues here. You're using `join()` with string as argument, so in that example you would have `W i n t e r` printed. Another issue is that code fails when you have 3 words or more in the variable `name`. I guess you forgot to add `*` in your unpack, like this: `first, *last = name.split()` to fix all issues. – Danilo Akamine Jul 01 '20 at 15:00
0

Based on Gaurav answer, a more complete function could be:

def split_full_name(full_name):
    """
    Split full name into first and last name based on white spaces.
    Being first_name the first word and last_name the rest of the string.
    """
    n = full_name.find(" ")
    if n < 0:
        return full_name, ""
    return full_name[:n].strip(), full_name[n:].strip()

first_name, last_name = split_full_name("Gaurav Meena")

maoaiz
  • 165
  • 1
  • 10
0

Here is what I used in my code instead of a for loop:

name_parts = name.split()
first_name = name_parts[0]
last_name = " ".join(name_parts[1:]) if len(name_parts) > 1 else ""