You are reading solutions / Python
alfie-grace-headshot-square2.jpg
Author: Alfie Grace
Data Scientist

Python TypeError: sequence item N: expected string, list found

TypeError: sequence item N: expected string, list found

A quick and easy way of fixing this error is by applying the map() function to your join() argument:

nested_list = ['This', 'is', 'a', 'list', 'with', 'a', ['nested', 'list']]

' '.join(map(str, nested_list))
Out:
"This is a list with a ['nested', 'list']"

In this example, map() is transforming every value in nested_list() to string-type, allowing join() to concatenate all of the list values. This process is explained more in-depth in the map() section of this article.

Why does this occur?

This error occurs because the list passed as an argument to the join() method contains a nested list. join() can only concatenate string-type objects, so Python throws an error if we use join() with anything that isn't a string.

As a result, using join() with a list containing integers, floats, or tuples results in a similar error, with list found being replaced by int found, float found, or tuple found.

Today we'll take a look at an example case of where we might see this error, along with some solutions that demonstrate how we can solve it.

Solution 1: for loop, generator, or list comprehension

As mentioned in the intro, this error occurs when we apply the join() method while using a list that contains a nested list.

Let's say you're analyzing some vehicle data. You've got a JSON file that contains data for different vehicles in the following format:

vehicle_details = {
    'vehicle_id' : '1',
    'make': 'Jaguar',
    'model': 'F-Type',
    'available_colors': ['yellow', 'red', 'blue'],
    'year': '2021'
}

We want to view all of the values for a given vehicle. We could try to do this using our Jaguar example with the following:

vehicle_info = vehicle_details.values()

' '.join(vehicle_info)
Out:
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-3-4d31652d781c> in <module>
----> 1 vehicle_info = vehicle_details.values()
      2 
      3 ' '.join(vehicle_info)
NameError: name 'vehicle_details' is not defined

As the error shows, sequence item 3 (the available_colors row) is a list, which means join() won't work here. We can get around this by using a for loop, generator, or list comprehension. Here's an example using a generator:

vehicle_info = vehicle_details.values()

' '.join(str(info) for info in vehicle_info)
Out:
"1 Jaguar F-Type ['yellow', 'red', 'blue'] 2021"

The generator iterates through each list item and converts the value to a string-type object, allowing join() to work.

Solution 2: map()

We can also troubleshoot this error using the map() function, as shown in the intro. We can apply map() to our vehicle example as follows:

vehicle_info = vehicle_details.values()

' '.join(map(str, vehicle_info))
Out:
"1 Jaguar F-Type ['yellow', 'red', 'blue'] 2021"

map() works by looping through a list given as the second argument. In our case, this is vehicle_info. It then applies whichever transformation function we provide as the first argument. Using str() as our transformation function converts everything in the list to a string, including our list of colors.

On the surface, a generator essentially goes through the same process as the map() function does, iterating through each item in the list and then applying the str() function. However, Python works its way through the statements very differently, with map() executing much faster than a generator. See below for a speed comparison of our two examples, which shows that our script runs faster while using map():

vehicle_info = vehicle_details.values()

# Create anonymous functions
gen = lambda: ' '.join(str(info) for info in vehicle_info)
mapping = lambda: ' '.join(map(str, vehicle_info))

# Calculate timings
gen_time = %timeit -o -q gen()
map_time = %timeit -o -q mapping()

# Create data table
data = [['map()', map_time.average], ['generator', gen_time.average]]
df = pd.DataFrame(data, columns=['type', 'microseconds'])
df.microseconds = round(df.microseconds * 1e6, 2) 
df.sort_values('microseconds', inplace=True)

df
Out:
typemicroseconds
0map()1.25
1generator1.56

Summary

The error TypeError: sequence item N: expected string, list found occurs when using the join() method with a list containing a nested list inside it. Similar errors can also be caused by applying join() using a list containing integers, floats, or tuples.

We need to convert list values to string-type objects before join() is applied to avoid this error. We can implement string conversion using the str() function combined with either the map() function or a for loop. Of the two options, we recommend using map(), as it is the faster of the two.

Take the internet's best data science courses Learn More

Meet the Authors

alfie-grace-headshot-square2.jpg

Alfie graduated with a Master's degree in Mechanical Engineering from University College London. He's currently working as a top-rated data scientist on Upwork. Find him on LinkedIn.

Brendan Martin
Editor: Brendan Martin
Founder of LearnDataSci

Get updates in your inbox

Join over 7,500 data science learners.