Indexing of a Tuple: all_data[1:] vs all_data[1]

Screen Link: https://app.dataquest.io/m/316/functions%3A-intermediate/6/returning-multiple-variables

My Code:

def open_dataset(file_name='AppleStore.csv', header=True):        
    opened_file = open(file_name)
    from csv import reader
    read_file = reader(opened_file)
    data = list(read_file)
    
    if header:
        return data[0], data[1:]
    else:
        return data
    
all_data = open_dataset()
header = all_data[0]
apps_data = all_data[1:]

print(header)
print(apps_data)

What I expected to happen:
To have my answer accepted :slight_smile:

What actually happened:
Answer was not accepted.

apps_data is a tuple, but we expected it to be a list.
apps_data is shorter than we expected.

I understand that the correct answer for apps_data variable is apps_data = all_data[1], however I’m still confused with the error, “apps_data is shorter than we expected.” Shouldn’t an index of 1 and 1: return the same data (albeit [1] in a list and [1:] in tuple)? Why would I get less data with [1:]?

2 Likes

Hello @eagle, welcome to the community!

The problem is in the slicing of the tuple in the following line:

apps_data = all_data[1:]

When you slice a tuple, the outcome is still a tuple, even if your slice only returns one item from the tuple. However, if you use indexing instead, the outcome is only the item in the position you passed.

In this case, all_data[1] is a list of lists, that’s why the answer checking mechanism says it expects a list. But when you slice the tuple you have this ([list of lists]), which is your lists os lists inside a tuple.

Also, when the website checks for the length of the object, it finds that the length is one because there is only one thing inside the tuple: your list os lists. It then tells you the it is shorter than expected.

You should run the following code instead:

apps_data = all_data[1]

Also, when a function returns more the one object, you can use the following syntax:

header, apps_data = open_dataset('AppleStore.csv')

Hope this solves your problem.

5 Likes

Thank you so much for the explanation. This helps me understand the concepts so much better - especially the difference of an index and the difference of a slice!

Also, thanks the suggestion on combing the return of objects from a function onto one line of code - forgot about that.

1 Like

Hi @eagle

Slicing returns a slice of the sequence and is always give the same type of class which sequence has, while indexing returns the item at that index and may have the different type of class from the original sequence.
for e.g.
Scenario:1

>>>a = (1,[2,3]) #which is a tuple having list
>>> a[1]
[2, 3]  #will give list because item on index 1 is a list, therefore
>>> type(a[1])
<class 'list'>  #its belong to class list while,

>>> a[1:] 
([2, 3],) #will give tuple because its "slicing" and 
>>>type(a[1:])
<class 'tuple'> #its belong to class tuple

So, when you do len(a[1]) will give you 2 and when you will do len([1:]) will give you 1 (which applies to your concern)

Scenario:2

>>> b=(1,(2,3)) # which is a tuple having tuple
>>> b[1]
(2, 3) # will give you a tuple because item on index 1 is a tuple, therefore
>>> type(b[1])
<class 'tuple'> #its belong to class tuple, while

>>> b[1:]
((2, 3),)  # will also give tuple after slicing and
>>> type(b[1:]) 
<class 'tuple'> #its belong to class tuple

Happy learning!

4 Likes