How to select only last names?

I did it in the following way:

author_last_names = [] for name in author_names: li = name.split() author_last_names.append(li.pop()) print(author_last_names)
authors = "Audre Lorde,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) #Collection of author last names author_last_names = [] for word in author_names: author_last_names.append(word.split()[1]) print (author_last_names)

why we will use For statement in this problem? please explain me. thanks

I am not sure why my solution is not accepted in the module. When the code below executes, the output is correct in the terminal but I receive an error " Value for author_last_names did not match the expected value."

authors = "Audre Lorde,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_names = ' '.join(author_names) author_names = author_names.split(' ') author_last_names = [] for i in range(1, len(author_names), 2): author_last_names.append(author_names[i]) print(author_last_names)

Hi Dustinhall,

What do the instruction state? What is the expected output type suppose to be (ie., None, string, list etc,) ? Try wrapping the code in a function and returning the result:

def solve(names):
    author_names = authors.split(',')
    author_names = ' '.join(author_names)
    author_names = author_names.split(' ')
    author_last_names = []
    for i in range(1, len(author_names), 2):
        author_last_names.append(author_names[i])
    return author_last_names


if __name__ == '__main__':
    authors = "Audre Lorde,Gabriela Mistral,Jean Toomer,An Qi,Walt Whitman,Shel Silverstein,Carmen Boullosa,Kamala Suraiyya,Langston Hughes,Adrienne Rich,Nikki Giovanni"

    print(solve(authors))

Let me know if that works for you.

Hello. So far, this was one of the most enjoyable challenges.
I need some help, seeing that my attempt at a solution was not a ‘for loop’ but rather a ‘list comprehension’.
The problem is that I got stuck with one major issue: What can I add to my list comprehension code (blue box on attached screenshot) so that the end result is the same as the answer provided (orange box).

Thank you.

In your screenshot, author_names is a list of strings.

I don’t quite understand the motivation behind your choice of [::-2] for the slice in the blue box. But putting that aside for the time being, your code in the blue box is doing:

author_names[i].split(" ") splits the string on whitespace and creates a list of the words (Since whitespace is the default, so instead of .split(" "), you could write it as .split() if you want).

author_names[i].split(" ")[::-2] slices the above list and saves the result in a list.
If instead of a list, we were slicing a string, the result would also be a string e.g.

print("abcdefghij"[::-2])
# Output: "jhfdb"

print(["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"][::-2])
# Output: ['j', 'h', 'f', 'd', 'b']

This is why in your blue box output, the last name strings are in lists e.g.

"Audre Lorde".split(" ") 
# Split method creates a list
# ["Audre", "Lorde"]

"Audre Lorde".split(" ")[::-2]
# Slicing a list returns a list
# ["Lorde"]

If instead of slicing, you use the element index to select the last word of the split words, then you will get same output as orange box:

# You wrote:
author_last_names = (author_names[i].split(" ")[::-2] for i in range(0, len(author_names)))

# Changing from slicing a list to indexing an element of the list
author_last_names = (author_names[i].split(" ")[-1] for i in range(0, len(author_names)))
print(list(author_last_names)) # Same output as orange box 

A few more remarks:

  • In your blue box code, you are using i to loop over the index of the author_names and then you access the name by author_names[i]. Since you aren’t doing any re-assigning, you don’t really need to keep track of the index. Instead you can loop over the elements directly.

  • Also, because you chose to use parentheses () instead of square brackets [], so in your blue box code author_last_names actually ends up being a generator object. You then have to convert this object to a list when you want to print it i.e. print(list(author_last_names))

Keeping in view the above observations, you could write the code in blue box as a list comprehension like so:

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

print(author_last_names)

Now author_last_names is a list instead of a generator object.

1 Like

Thank you! Very helpful indeed.

1 Like

Now that I checked for this explanation, it all makes sense.

I solved it by using for loops but it’s ofc not nearly as concise as the provided answer:

author_names = authors.split(‘,’)
print(author_names)

author_all_names =
author_last_names =
for n in author_names:
author_all_names.append(n.split())
for n in author_all_names:
author_last_names.append(n[1])

I think the developer of the course should at least give an example of .split() being followed by an index in the introduction. That way it would be less confusing. At least for me I didn’t realize I could directly use index after a built in method

2 Likes

I agree with you: in a number of introduction notes, the explanations are not very detailed.

I also receive this code if the answer is correct but doesn’t match the “expected answer”.
Makes me think that the course organisers only had one solution per challenge, which is strange, given that for most programming challenges, a few possible answers could exist.

Can you share the latest code for your solution? Also, what exact feedback/error message is being shown?

It is probable that your code may not be working as stipulated for certain edge cases. There may also be some test cases which aren’t visible to the coders, but are being used by the system to validate the results for different arguments.

In dustindhall’s solution, if the argument is a bit different, then the code doesn’t return the expected output.
For Example,

// Works for this
authors = "Audre Lorde,Gabriela Mistral,Jean Toomer,An Qi,Walt Whitman"
...
print(author_last_names)
// ['Lorde', 'Mistral', 'Toomer', 'Qi', 'Whitman']

// Doesn't work correctly for this
authors = "Audre Lorde,Gabriela Mistral,Jean Nathan Toomer,An Qi,Walt Whitman"
...
print(author_last_names)
// ['Lorde', 'Mistral', 'Nathan', 'An', 'Walt']
// The middle name of one of the authors breaks the logic of dustindhall's solution
// which assumes that every second word is the last name.

My first time actually using the forum to ask a question, hope I’m even in the right place. So… I got the question right, but I feel like there must be a way to do both functions in one list comprehension. If there is anyone able to explain to me how? (I did try, couldn’t figure it out) Otherwise if there isn’t a way also just letting me know that would be helpful lol.

authors = “Audre Lorde,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)

last_names = [i.split() for i in author_names]

author_last_names = [i[-1] for i in last_names]

print(last_names)
print(author_last_names)

One way to do so would be:

authors = "Audre Lorde,Gabriela...,Nikki Giovanni"

author_names = authors.split(',')

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

print(author_last_names)

authors is a string of names separated by commas.

Splitting the authors string using comma (as the delimiter for the separation) creates a list of strings. This list is assigned to author_names.

In the list comprehension, the for loop iterates over each string in the author_names list and assigns it to the variable name.

name.split()[-1]

First the split method splits the string on whitespace and creates another list. Then the index [-1] allows us to target the last element of the list i.e. the last name.

You could also do:

authors = "Audre Lorde,Gabriela...,Nikki Giovanni"

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

print(author_last_names)

But, it is probably easier to follow what is going on in the former snippet compared to the latter one-liner.

1 Like

No those are both great. I’m a lot further in since I posted that but seeing problems done multiple different ways is a lot of help to perceive the options I have mentally. Thank you for that! The second answer is what I was really looking for/trying to do, couldn’t get it through my head why I couldn’t make it work in one list comprehension. While I have ya here mind if I ask another question? I am doing " Casual Coded Correspondence: The Project" on jupyter notebook.
And I have been playing around trying to figure out if there’s a way to only iterate the proper result from this function…

vishals_encrypted_message3 = 'vhfinmxkl atox kxgwxkxw tee hy maxlx hew vbiaxkl tl hulhexmx. px\'ee atox mh kxteer lmxi ni hnk ztfx by px ptgm mh dxxi hnk fxlltzxl ltyx.'

def caesar_decryption(message, offset):
    decrypted_message = ''
    for letter in message:
        if letter not in alphabet:
            decrypted_message += letter
        else:
            decrypted_message += alphabet[(alphabet.index(letter) + offset) % len(alphabet)]
    return decrypted_message

for x in range(len(alphabet)):
    print(caesar_decryption(vishals_encrypted_message3, x))

#Originally I tried using the .format() method inside the loop in the function to iterate through, create and return multiple variables so I could use a...

variables being made like variable_attempt{x}.format(x) = 'result from this iteration'

if x in vishals_encrypted_message3:  
    elif  x2 in vishals_encrypted_message3:
        Etc...
return variable{x}

where x1 is ‘to’, x2 is ‘is’, x3 is ‘the’ and so on with common words in all sentences. The return variable{x} being that iteration of the main function loop. I couldn’t get it to work though so I guess you cant use .format() like that, does anything come to mind for you or do you see someone I did wrong? I think I’m probably trying a bit too hard to learn too fast using concepts I don’t understand enough yet when I don’t need to, but I find that concept a really powerful one if it cant work so if it can id like to know. (Hope I explained that well enough, all my (x)s are just variables for the variables not indicative of what they actually were).

(I’m still just getting used to the forums btw, sorry thats not formatted well. Only my 3rd post here and only been studying on codecademy like 8-9 days)

Say for example you have a list of just two elements/items:
e.g: my_list = [‘a’, ‘b’] using [1] to access the last element/item [1] will work. But in a situation where you have more than two elements/items in a list, that won’t work as [1] will only give you the element/item at the second index.

Using the negative index notation helps us access the elements/items in the list from the right hand side.
So, say will have a list containing 5 elements/items.
e.g: my_list = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’] to access the last element/item in the list, you use [-1]
print(my_list[-1])
To access the second to the last element/item you use [-2]
print(my_list[-2]

And so on and so forth.

I hope this was helpful!

You can break it down this way which is easier to understand:

authors = “Audre Lorde,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 = [ ]

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

print(author_last_names)

Thank you for this solution.

I tried what I believe to be the same thing, but I’m getting a different result.

author_last_names =

for names in author_names:

last_names = names.split()[-1]

author_last_names.append(last_names)

print(author_last_names)

The difference being that I assigned names.split()[-1] to a new variable. And then appended that variable to author_last_names.

This code prints only the very last item on the list. Can anybody explain why, please?

doesn’t pop() by default remove the last item(when the parenthesis is empty)? how did it remove the first name?

To preserve code formatting in forum posts, see: [How to] Format code in posts

Indentation is important in Python.

Based on your observation, I suspect your code is:

author_last_names = []
author_names = author_names.split(",")

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

print(author_last_names)

Since the append statement is outside the loop, so it is executed only once. Hence, the output mentioned by you. You should consider making the append statement a part of the loop’s body by indenting it properly,

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