How to select only last names?

EDIT - THIS CODE IS A WORKING SOLUTION WITH ONE MISTAKE, CORRECTED IN EDIT
Why am I getting an error here?

authors = "Audre Lorde, William Carlos Williams, Gabriela Mistral, Jean Toomer, An Qi, Walt Whitman, Shel Silverstein, Carmen Boullosa, Kamala Suraiyya, Langston Hughes, Adrienne Rich, Nikki Giovanni"

author_names = authors.split(",")
author_last_names = [each.split()[1] for each in author_names]

If i print(author_last_names) i get the expected print of:

[‘Lorde’, ‘Carlos’, ‘Mistral’, ‘Toomer’, ‘Qi’, ‘Whitman’, ‘Silverstein’, ‘Boullosa’, ‘Suraiyya’, ‘Hughes’, ‘Rich’, ‘Giovanni’]

but regardless I keep on getting error:

Value for author_last_names did not match the expected value

Anyone? No compilation errors…

//EDIT:
Okay found my mistake, some names have first and midle names, so instead of using index count from the front, I should count from the last.
So this line:

author_last_names = [each.split()**[1]** for each in author_names]

Has to look like this:

`author_last_names = [each.split()**[-1]** for each in author_names]`

I did exactly this, but for me it creates a new list containing the last letter of each last name. Are you sure this worked for you?

A completely different approach to consider for extra study…

def name_split(name):
    temp = name.split()
    return {
        'first': temp.pop(0),
        'last': temp
    }

for author in author_names:
    first_last = name_split(author)
    author_first_names.append(first_last['first'])
    author_last_names.append(first_last['last'])

The name_split() method takes the first name off the list then assigns the remainder to the last name. This would work for names like,

Florence Rost van Tonningen

or,

Richard Van Dyke
2 Likes

I had the same question. It doesn’t seem to be just the [-1], if we run the same code with .append() it adds the full last name. why does the use of ‘+=’ break it down at the letter? The [-1] should be selecting the last element of the list either way, which is a full last name!

For example I have two lines of code:

authors = "Audre Lorde, William Carlos Williams, Gabriela Mistral, Jean Toomer, An Qi, Walt Whitman, Shel Silverstein, Carmen Boullosa, Kamala Suraiyya, Langston Hughes, Adrienne Rich, Nikki Giovanni"

author_names = authors.split(',')

print(author_names)

author_last_names = []
for name in author_names:
  author_last_names.append(name.split()[-1])
  
print(author_last_names)

This gives me the following output:

['Audre Lorde', ' William Carlos Williams', ' Gabriela Mistral', ' Jean Toomer', ' An Qi', ' Walt Whitman', ' Shel Silverstein', ' Carmen Boullosa', ' Kamala Suraiyya', ' Langston Hughes', ' Adrienne Rich', ' Nikki Giovanni']
['Lorde', 'Williams', 'Mistral', 'Toomer', 'Qi', 'Whitman', 'Silverstein', 'Boullosa', 'Suraiyya', 'Hughes', 'Rich', 'Giovanni']

OR

authors = "Audre Lorde, William Carlos Williams, Gabriela Mistral, Jean Toomer, An Qi, Walt Whitman, Shel Silverstein, Carmen Boullosa, Kamala Suraiyya, Langston Hughes, Adrienne Rich, Nikki Giovanni"

author_names = authors.split(',')

print(author_names)

author_last_names = []
for name in author_names:
  author_last_names += (name.split()[-1])
  
print(author_last_names)

Which gives me this:

['Audre Lorde', ' William Carlos Williams', ' Gabriela Mistral', ' Jean Toomer', ' An Qi', ' Walt Whitman', ' Shel Silverstein', ' Carmen Boullosa', ' Kamala Suraiyya', ' Langston Hughes', ' Adrienne Rich', ' Nikki Giovanni']
['L', 'o', 'r', 'd', 'e', 'W', 'i', 'l', 'l', 'i', 'a', 'm', 's', 'M', 'i', 's', 't', 'r', 'a', 'l', 'T', 'o', 'o', 'm', 'e', 'r', 'Q', 'i', 'W', 'h', 'i', 't', 'm', 'a', 'n', 'S', 'i', 'l', 'v', 'e', 'r', 's', 't', 'e', 'i', 'n', 'B', 'o', 'u', 'l', 'l', 'o', 's', 'a', 'S', 'u', 'r', 'a', 'i', 'y', 'y', 'a', 'H', 'u', 'g', 'h', 'e', 's', 'R', 'i', 'c', 'h', 'G', 'i', 'o', 'v', 'a', 'n', 'n', 'i']

I really don’t understand why the ‘+=’ alone is changing what’s being added to the list. The [-1] should be selecting the last item, which is a full last name, not a letter.

I am surprised the second code goes well add all. This stackoverflow question explains it:

https://stackoverflow.com/questions/2347265/why-does-behave-unexpectedly-on-lists

which for me, is enough to steer clear of using +=, can only lead to trouble further down the road. patrickd explains it in this topic (earlier reply):

Thank you for making this so simple to understand!

Thank you, I still don´t quite get why we need to put our empty list outside the for Loop, but the explanation was very useful.

1 Like

Ok I just got it, I tried to put the empty list inside the for loop. It is indeed rewritten so the final result will be [‘Giovanni’] instead of [‘Lorde’, ‘Mistral’, ‘Toomer’, ‘Qi’, ‘Whitman’, ‘Silverstein’, ‘Boullosa’, ‘Suraiyya’, ‘Hughes’, ‘Rich’, ‘Giovanni’]

I need help.
i get how [-1] is used to append the last item in the list. But why does this work after name.split().
Never even realized that was possible. How does it work in this specific case??
I tried something like the solution but all it ever returned was the last letter of the last name. it never returned the full last name. How did a simple .split() put each name in its own list???
Can somone help me figure this out please

split splits a string into a list, using the separator specified (white space by default).

now that we have a list, accessing by index gives us the element/value of the list

accessing strings by index gives us characters.

My solution:

author_last_names = [name.strip().split()[-1] for name in authors.split(",")]

The primary sticking point in this discussion seems to be using [-1] to grab the last name, and more specifically why it’s grabbing a string of characters rather than the string’s last character.

First, we perform

>>> authors.split(",")
['Audre Lorde', ' William Carlos Williams', ' Gabriela Mistral', ' Jean Toomer', ' An Qi', ' Walt Whitman', ' Shel Silverstein', ' Carmen Boullosa', ' Kamala Suraiyya', ' Langston Hughes', ' Adrienne Rich', ' Nikki Giovanni']

This is the first step, which gives us a list of strings. We can index elements of a list as well as iterate over a list (which is our next objective).
(Breaking up the list comprehension for readability we have:)

for name in authors.split(","):
    name.strip().split()[-1]

At each pass of this loop, name becomes the next element of authors. Remember that a list can contain other lists, which is essentially what we have here. As we loop through our list of author names, name becomes the next full name string. Reading the for loop’s action from left to right, we are first doing

>>> name.strip()
'William Carlos Williams'

This removes leading and trailing whitespace (those spaces we identified next to the commas from earlier). Because name.strip() evaluates to ‘William Carlos Williams’ (on some pass), our next step essentially looks like

>>> 'William Carlos Williams'.split()
['William', 'Carlos', 'Williams']

which is a list of one author’s full name, and we want the last name (the last element of this list). We get that by index -1.

TL;DR:
name.strip().split()[-1] evaluates to
‘William Carlos Williams’.split()[-1] evaluates to
[‘William’, ‘Carlos’, ‘Williams’][-1] evaluates to
‘Williams’

1 Like

Here’s another solution - maybe it’s a bit convoluted, but takes fewer lines than most of the other solutions proposed

author_names = authors.split(',')

author_last_names = [name[:-1] for name in authors.split() if "," in name] + [author_names[-1].split()[-1]]

So using a list comprehension, iterate through all names, only select the names that contain “,”, then slice out the “,”, then concatenate the final last name which wouldn’t contain the “,” since it’s the final element of the author_last_names list.

1 Like

Hi, I wanted to ask a general question about the specific approach you outlined. Specifically,

  1. State your goal - what do you want to do with your data?
  2. What format is the data already in?
  3. What steps are necessary to do what you want?

seem like the 3 steps you are using to solve the problem. Is this the problem solving framework that expert programmers use when approaching any problem?

Thank you for any advice.

nope this does not do the exact job…

This code giving me the write answer but the system says it is wrong
giving me this message " Value for author_last_names did not match the expected value."

author_names = authors.split(',')
#print(author_names)
for word in author_names:
  new_word = word.split()
  #print(new_word)
  author_last_names = []
  author_last_names.append(new_word[-1])
  print(author_last_names)

Maybe you could look yourself and see if you agree with said system?
What value does that variable refer to after your code has finished, and what should it be? That’s what that message is saying is the problem, so that’s something you could look at.

If you by right answer mean that you’re looking at something being printed out, then that’s not what the error message is complaining about, if that’s the case you’re looking at the wrong thing.

And then if you do end up agreeing that this is wrong, you could start making observations about what individual operations you’re carrying out. When exactly does your code do something that you don’t agree with?

1 Like

I was trying comprehension list as well and I’ve got it with this one:

author_last_names = [ author.split()[-1] for author in author_names]

Hello digitalmaster74014,

I see the code works, but how did you decide on ‘author.split()[-1]’?
I tried so many times but it will not split the last name even when using [-1].

thanks.

Hello ruby9015521395,
With this comprehension list I loop through each author in the original list; I split each authors ítem which then turns into an individual list of [name, lastname], and then I select the first negative index of each of this individual lists.

I was actually pretty close but how come mine doesn’t work? (See below).

author_last_names =
for name in author_names:
name.split()[-1]
author_last_names.append(name)