Trouble with carlys clippers exercise in python course

Hey I’m doing the carlys clippers and confused with the last line that asks us to

Carly thinks she can bring in more customers by advertising all of the haircuts she has that are under 30 dollars.

Use a list comprehension to create a list called cuts_under_30 that has the entry hairstyles[i] for each i for which new_prices[i] is less than 30 .

You can use range() in your list comprehension to make i go from 0 to len(new_prices) - 1 .

I’m wondering about cuts_under_30 = [hairstyles[i] for i in range(len(hairstyles)) if new_prices[i] < 30] where it has to be range(len(hairstles)) when i print range(len(hairstyles it says range 0, 8 isn’t this already implied? when I try to run the code without the range len it gets TypeError: list indices must be integers or slices, not str maybe i feel there’s jsut an easy way to do it.

https://www.codecademy.com/paths/computer-science/tracks/cspath-flow-data-iteration/modules/dspath-python-loops/projects/carlys-clippers

1 Like

Hi, Miles, here’s my understanding of what you are asking:. You are using the list data type, specifically parallel lists. You are interested in something in list B that has the same position in the list (i.e., index) as another item’s position in list A. Actually, your solution does the job very well. But you do not want to use range(). Is that it??

I guess you have tried [hairstyle for hairstyle in hairstyles if something_in_price] but just what is something_in_price? You have no way of tying each hairstyle (list A) to a price (list B) without using indexing, and one way to do that is to use range(len(list)), as you have done. You could use the list.index() method, but that is pretty inefficient, as it requires a search through the list each time (obviously no big deal with a list of length 8, but …)

If you have covered the functions enumerate() or zip(), one or the other of those could also be used. (Many of these parallel list problems are better handled using the dictionary data type, but that is not what today’s lesson is about.)

3 Likes

The objective is to return a list of hairstyles that are priced below 30$. We know that both lists correspond so we can iterate over a range to get their indices…

[hairstyles[x] for x in range(len(new_prices)) if new_prices[x] < 30]

This is what is expected in the exercise. However, as @patrickd314 mentioned, there are other ways.

zip is a function for pairing up corresponding values in two separate sequences.

>>> list(zip("Python", "Python"[::-1]))
[('P', 'n'), ('y', 'o'), ('t', 'h'), ('h', 't'), ('o', 'y'), ('n', 'P')]
>>> 

Given a zipped list, we don’t need the index, just the values.

>>> [x[0] for x in zip(hairstyles, new_prices) if x[1] < 30]
['bouffant', 'pixie', 'crew', 'bowl']
>>> 

It follows that you will have learned this in a lesson at some point, or it should not be used, yet. Still, nothing to keep us from learning a little extra as we go, just so long as we first complete the exercise as expected. After passing we can go to town playing with the code and what we can learn about it.

To make it even more abuntantly clear, we can show how for can unpack each tuple in the zipped list…

>>> [a for a, b in zip(hairstyles, new_prices) if b < 30]
['bouffant', 'pixie', 'crew', 'bowl']
>>> 
5 Likes

Hello,
I’ve got the question as I’m also struggling with this part of Carly’s Clippers.
I do not understand, why do I have to use range in:

[hairstyles[x] for x in range(len(new_prices)) if new_prices[x] < 30]

I tried to use something like that:

cuts_under_30=[hairstyles[x] for x in new_prices if new_prices[x]<30]

because I thought it that the appropriate elements of hairstyles list would fill the new_prices list.
What’s wrong with my way of thinking?

Greetings

range will give us a sequence which we can use to poll the value at each index in the list. There are two lists, one for hairstyles, and one for prices. They both correspond so the price at index x will be for the hairstyle at index x.

We cannot use a read only loop since it will give us the value, not the index, which is what we need if we are to pair up with the other list.

Ok, I see, thank you. :sunglasses:
But let me know if I understand this part of code corretly:

cuts_under_30=[hairstyles[x] for x in range(len(new_prices)) if new_prices[x]<30]
print(cuts_under_30)

I understand it that way:
if new_prices<30 : take its index (I mean “the place” in which the numbers are kept: for this example it would be 0,1,2,3)

and
into these places put the hairstyles
so:
‘bouffant’ --> to the place of 0
‘pixie’ --> to the place of 1
‘crew’ --> to the place of 2
‘bowl’ to the place of 3
Do I understand it properly?

1 Like

Yes, it looks like you have the idea.

x    hairstyles     prices
1    "bouffant",      30
2    "pixie",         25
3    "dreadlocks",    40
4    "crew",          20
5    "bowl",          20
6    "bob",           35
7    "mohawk",        50
8    "flattop"        35

The range produces the indices. The hairstyle at index x corresponds to the price at index x.

Hi mtf, just to confirm. The hairstyles should correspond to the “new_prices” and not “prices”, correct?

The column heading is for the customer. We control what is displayed. Not sure that helps answer your question.