# FAQ: String Methods - Splitting Strings II

amazing… but how does it work? ```
[::-1]

One line: For each author name, split it by the spaces and select the last item in the resulting array:

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

e.g.
William Carlos Williams becomes [“William”, “Carlos”, “Williams”] once split.
We then select the last index using -1, which is “Williams” to get our answer.

Hello everyone! So, to start with, this is my first time actually posting anything here, and I don’t really know if this is the right place to post this, but here goes. I already got through this stage, but I reaally don’t think I solved it in the most optimal of ways. I’d very much appreciate it if someone were to critique it. I came up with this solution on my own btw, no tips or anything so be gentle lol.

last_name = “”
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)

for name in range(0, len(author_names)):
current_name = author_names[name]
#print(current_name)
for letter in range(-1, -len(current_name), -1):
#print(current_name[letter])
#print(letter)
if current_name[letter] == " ":
last_name += current_name[letter + 1:] + " "
#print( “I found a space. I should stop here.”)
break
#print(last_name)

last_names = last_name.split(" ")
author_last_names =

for name in range(0, len(last_names)):
print(name)
author_last_names.append(last_names[name])

author_last_names.pop()
print(last_names)
print(author_last_names)

If you are referencing -1 of a string it will return the last letter in the string, for example: str1 = ‘hello there’ , str1[-1] = e
if you are referencing -1 of a list containing strings it will return the last string in the list, for example: lst1 = [‘hello’, ‘there’] , lst1[-1] = there

Hi, first time poster. I had to see the solution for this one, and was wondering how an alternative would work so I tried the below:

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

when I print author_last_names it prints each letter of the last names like: [‘L’, ‘o’, ‘r’, ‘d’, ‘e’, ‘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’]

How would I correct this code?/Why does it split at each letter?

Thanks!

because of `[-1]`. Which gives you the last letter of a string or list

Thats much more elegant.

My solution:

``````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:
temp = name.split()
author_last_names.append(temp[-1])
``````

I’m having trouble understanding why this is outputting every letter in each string in the list instead of a single string per index value.

When I print the range(len(new_list))) I get a range of 0,25 but the output for new_list gives me a list containing each individual letter in each string.

Also, I realize that this method will not give me a correct list of last names, but I still would like to know why its giving the result it does. TIA!

``````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)

#Split the authors names
def first_last_split(list):
new_list = []
for i in list:
new_list += i.split()
return new_list

print(first_last_split(author_names))

#Check new_list range value
new_list = (first_last_split(author_names))
print(range(len(new_list)))

#Take each odd index value in new_list and
def last_list(list2):
last_name_list = []
for x in range(len(list2)):
if x % 2 != 0:
last_name_list += new_list[x]
return last_name_list

print(last_list(new_list))

``````

So each element NAME is split by space into individual list elements. I.e. ‘William Carlos Williams’ becomes ‘William’, ‘Carlos’, ‘Williams’. I get that part. But how is it clear that [-1] should then apply to ‘Williams’ and not the last item of the full author_names list.

Does the [-1] term reference the last variable in some temporary split list that’s been created? TIA!

This is pretty interesting! First, with the line, `print(first_last_split(author_names))`, you run the function one time, mutating the list, author_names. Then you run it a second time with `new_list = (first_last_split(author_names))`, splitting one more time. Put in a print statement to print new_list, and you’ll see this.

Then, you call += on the list. With a list, += does not behave as you expect. It works somewhat like `list.extend(q)`, and with that method, q must be a list (Wrong! See edit.) But you are using it with a string, which, to extend the list, must be iterated over, providing the individual characters that extend the list.

``````empty_lst = []
empty_lst.extend('xyz')  # Using extend() with a string argument
print(empty_lst)
empty_lst += 'abc'
print(empty_lst)

# Output:
['x', 'y', 'z']
['x', 'y', 'z', 'a', 'b', 'c']
``````

Edit: extend() takes any iterable, not just a list, as an argument.

Thanks. I’ll try to wrap my head around that.

Follow up question. If I rewrote it using .append how could I get the for loop to iterate over the range but then use a split on the value at that range. The code I tried to use to do that is throwing an error:

``````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)

#Split the authors names
def first_last_split(list):
new_list = []
for i in list:
new_list += i.split()
return new_list

print(first_last_split(author_names))

def last_list(list2):
last_name_list = []
for [x] in range(len(list2)):
if x % 2 != 0:
last_name_list.append(x.split() [-1])
return last_name_list

print(last_list(new_list))
``````

TIA

The first error is that the variable name new_list is defined within the scope of the function first_last_split(), and is not visible in the global space, where you call `print(last_list(new_list))`, so you get `NameError: name 'new_list' is not defined`. So you should define it before that last print statement/function call like this:

``````new_list = first_last_split(author_names)
print(last_list(new_list))
``````

… and then be sure to comment out the first print statement, `print(first_last_split(author_names))`, because that one will run the function and alter the author_names, as I mentioned earlier.

Now you get to another problem :`for [x] in range(len(list2)):` Why is x made into a list? omit the brackets, and you are correctly obtaining the output of range, 0, 1, 2, 3 … len(list2) -1, and assigning it to the variable x each time around the ‘for’ loop.

But, what do you do with x = 0, x = 1, etc.?? This: `last_name_list.append(x.split() [-1])`, where you are applying str.split() to 0, 1, 2, … This throws another error: `AttributeError: 'int' object has no attribute 'split'`

What you want to do is use those x’s (integers) as indexes into your list of strings.

But you seem to be still trying with `if x % 2 != 0:` to somehow access every other name. Even with all the above errors corrected, that approach is not going to work, thanks to William Carlos Williams, who inconveniently has three names! If you reduce the entire author’s list to individual names, then output every other one, you will be wrong by the time you get to the second author, and forever after.

Take your initial author_names list, `['Audre Lorde', ' William Carlos Williams', ' Gabriela Mistral', ... , ' Nikki Giovanni']` , go through that list using `for author in author_names:` (notice: no len() or range() or index needed here!), and each time around, append() to a list `author.split()[-1]`.

1 Like

If we use .split() method without index[-1] we get Two-dimensional lists (arrays) :

``````author_names = ['Audre Lorde', 'Gabriela Mistral']

author_names_split = []
for i in author_names:
author_names_split.append(i.split())

print(author_names_split)
#[['Audre', 'Lorde'], ['Gabriela', 'Mistral']]
``````

But, if we use index[-1] we don’t get Two-dimensional lists (arrays), like:

``````>[['Lorde'], ['Mistral']]
``````

We get list like thise:

``````>['Lorde', 'Mistral']
``````

Why index[-1] change this?

The -1 index identifies the final element in a list.

s = “abc xyz”
s.split() gives [“abc”, “xyz”] (a list)
s.split()[-1] gives “xyz” (not a list)

2 Likes

This is what i have used to get last names
author_names = authors.split(’,’)

check =
for i in author_names:
x = i.split(’ ')
check.append(x)
print(check)

author_last_names=
for i in check:
author_last_names.append(i[-1])
print(author_last_names)

Explanation : first we make the string as a list by using author_names = authors.split(’,’)

secondly making the long list as sub list by below code :
check =
for i in author_names:
x = i.split(’ ')
check.append(x)
print(check)

Thirdly and last , append the last value to the empty list from every sub list as below :

author_last_names=
for i in check:
author_last_names.append(i[-1])
print(author_last_names)

HOPE THIS HELPS SOMEONE

It would be of more help were you to edit it to preserve the (non-optional) Python indentation by using the </> icon at the center of the menu bar atop the text box when it is open for typing.

let us assume, that the surname of one of the authors is not `Williams` but `Carlos Williams`. Than, we will have to use this code:

``````author_last_names = [i.split()[1:] for i in author_names]
``````

which creates list of lists:

``````[['Lorde'], ['Carlos', 'Williams'], ['Mistral'], ['Toomer'], ['Qi'], ['Whitman'], ['Silverstein'], ['Boullosa'], ['Suraiyya'], ['Hughes'], ['Rich'], ['Giovanni']]
``````

It creates a problem: how to flatten or break the list of lists? WITHOUT SELF-WRITTEN FUNCTION, but via implemented Python functions! I’ve digged all the internet and found the only slim solution, which, unfortunatelly works only with print:

``````print(*author_last_names)
``````

gives desirable result:

``````['Lorde'] ['Carlos', 'Williams'] ['Mistral'] ['Toomer'] ['Qi'] ['Whitman'] ['Silverstein'] ['Boullosa'] ['Suraiyya'] ['Hughes'] ['Rich'] ['Giovanni']
``````

but if I try to assign expression to the new variable:

``````author_last_names_fixed = *author_last_names
``````

it througs the error:

``````  File "script.py", line 8
author_last_names_fixed = *author_last_names
^
SyntaxError: can't use starred expression here
``````

Note that the output of `print(*author_last_names)` is

``````['Lorde'] ['Carlos', 'Williams'] ['Mistral'] ['Toomer'] ['Qi'] ['Whitman'] ['Silverstein'] ['Boullosa'] ['Suraiyya'] ['Hughes'] ['Rich'] ['Giovanni']
``````

This is simply a sequence of lists; it is not a Python data type that can be assigned to a variable.

The * “operator” is meant to be used within a function call, as you have done with print(); it will not work to simply provide a sequence to assign to a variable.

1 Like