# Carly's Clippers Project Question

I understood each task in this project until I got to task #12. Here is a screenshot of the task and the hint associated with this task:

And here is the code I wrote for this task (which is correct, I believe - I watched the Project Walkthrough to see the answer but still didnâ€™t completely understand the explanation):

``````cuts_under_30 = [hairstyles[i] for i in range(len(new_prices)) if new_prices[i] < 30]
``````

I think what I donâ€™t really understand is the range part of this code. Iâ€™m a little confused about the `i` variable and the indexes as well. If someone could explain this task to me I would really appreciate it!

1 Like

The range is the range of the length of the list new_prices. For example:

``````new_prices = [1, 2, 3] #The range of this is 0-2 (using python indexing). The length is still 3.
``````

Therefore, the forâ€¦of loops and the if block are both iterating through the individual elements of the list, until the index of the list reaches the end of the list. For example:

``````list1 = [1, 2, 3]
for i in range(len(list1)):
print i #this will print i, which is each individual element in the list 'list1', until the loop gets to the last index of the list.
``````

Then in the if block, the code checks to see if the element at the index i of the new_prices list is less than thirty.
If my explanation does not make sense, please ask, and I will try to clarify it as best as I can!

1 Like

Basically, it checks to see if the element of the list new_prices, at the index â€˜iâ€™ is less than thirty, and then in a way, adds 1 to i, and repeats that process. It does this until (the forâ€¦of loop) the value at the index of i is at the end of the range of the list.
Please ask me to clarify if this does not make much sense!

1 Like

I get the impression that what youâ€™re actually struggling to understand is the list comprehension, so letâ€™s review that.

The list comprehension is:
`[hairstyles[i] for i in range(len(new_prices)) if new_prices[i] < 30]`

If we consider a simpler list comprehension, such as:
`[x for x in range(10)]`
what we get is:
`[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]`

The list comprehension adds an item, `x`, if it meets the condition `for x in range(10)`. Hence, we get all the integers from 0 to 9 inclusive.

So, our original comprehension of `[hairstyles[i] for i in range(len(new_prices)) if new_prices[i] < 30]` works in a similar way.

It will add every item, `hairstyles[i]`, to the list which matches the condition. In this case, our condition is:

`for i in range(len(new_prices)) if new_prices[i] < 30`

Letâ€™s assume there are 10 haircuts, and 10 prices in the `new_prices` list. This condition will check each of them in turn (the `for i in range(len(new_prices))` bit) to see whether theyâ€™re under 30 bucks (the `if new_prices[i] < 30` bit).

If this condition is met, then `hairstyles[i]` goes into the list. If not, it doesnâ€™t.

Hopefully thatâ€™s made it a bit clearer, but do let us know if youâ€™re still stumped.

2 Likes

@tera5288723178 this does make sense, thank you very much! It was just a little tough for me to wrap my head around at first.

@thepitycoder thank you so much for your thorough response! This was extremely helpful. Thank you for breaking down each part of the code and explaining it to me with examples. I definitely understand it a lot better now that Iâ€™ve seen it broken down. Thank you again!

list comprehensions do a little more than just one loop/condition:

``````[ RESULT
# any number of for/if:
for this in these
if sky is purple
for pickle in jar
for color in [black]
if whatever
if i.feel.like.it
]
``````

You can think of it much like completely normal code where you have the ability to take values out of iterables, and also the ability to skip combinations.

It commonly gets used to implement map/filter and those are single loops, thatâ€™s what youâ€™ll usually see, but thatâ€™s not a limitation of list comprehension.

One limitation though, the first thing has to be `for`, so this is not allowed:

`[ RESULT if something ]`
even though that actually makes perfectly good sense, that would produce a list of either zero or one results depending on the condition.

So if you for example have a list of lists representing a grid (a chessboard, perhaps), then you could use list comprehension to iterate through it. First youâ€™d have to iterate through rows, and a row is several cells so that needs iterating through as well:

``````grid = ['abcd',
'efgh',
'ijkl']

[ (x, y, value)
for (y, row) in enumerate(grid)
for (x, value) in enumerate(row)
]

# (0, 0, 'a'), (1, 0, 'b'), ...
``````
2 Likes

Why are other hairstyles with prices less than 30 not showing when printed

`cuts_under_30 = [hairstyles[i] for i in range(len(new_prices)) if new_prices[i] < 30]`

I canâ€™t find an error in the comprehension you have provided. Is there an error code when you attempt to print this list? This may need a little more information to solve.

1 Like

Also, @kcde, are you actually printing the list somewhere else in the code?

(Itâ€™s hard to debug an entire program from just one line of it. )

I get â€˜TypeError: object of type â€˜generatorâ€™ has no len()â€™ error every time i try to initiate the code
cuts_under_30 = [hairstyles[i] for i in range(len(new_prices)) if new_prices[i] < 30]

Even though itâ€™s similar to the one from the walkthrough. I donâ€™t quite get it(

Found my own mistake - i didnâ€™t covert new_prices into list and there was no len() in this generator.
Once i did new_prices2 = list(new_prices) and changed my initial code to cuts_under_30 = [hairstyles[i] for i in range(len(list(new_prices2))) if new_prices2[i] < 30] it worked perfectly fine!

Edit: You caught your error before I replied . You can skip creating the generator in the first place if you make sure to use square parantheses.

Itâ€™s really hard to tell for certain without more of your code but I believe you have used curly instead of square parantheses when creating new_prices. Does your code use something like the following line-

``````new_prices = (price-5 for price in prices)
``````

``````new_prices = [price-5 for price in prices]
``````

Using curly braces will provide you with a generator object which is not something you need to worry about at this point in the lessons. No doubt theyâ€™ll crop up again as they are very useful but stick with list comprehensions for now.

1 Like

1 Like

Hi, thanks for that.

If I run your code, I get the following:

``````>>> print(cuts_under_30)
['bouffant', 'pixie', 'crew', 'bowl']
``````

This is the correct output, as you only have 4 values in your `new_prices` list which are below 30. We can show this by doing the following:

``````>>> for a,b in zip(hairstyles,new_prices):
print("%s costs \$%d" % (a,b))

bouffant costs \$25
pixie costs \$20
crew costs \$15
bowl costs \$15
bob costs \$30
mohawk costs \$45
flattop costs \$30
``````

As you can see, the hairstyles `bob` and `flattop` cost exactly `30`. However, your list comprehension is:

``````cuts_under_30 = [hairstyles[i] for i in range(len(new_prices)-1) if new_prices[i] < 30]
``````

The cost of the haircut must be less than 30, which is only true for 4 of your 8 haircuts.

If the condition were less than or equal (`<=`), then your output would be different:

``````>>> cuts_under_30 = [hairstyles[i] for i in range(len(new_prices)-1) if new_prices[i] <= 30]
>>> print(cuts_under_30)

['bouffant', 'pixie', 'crew', 'bowl', 'bob']
``````

Notice that `bob` has appeared in the list, but `flattop` hasnâ€™t even though their prices are the same. Can you figure out why?

2 Likes

Ahh. cause itâ€™s

thanks.
I actually thought more prices were less than 30. But looking at it now prices < 30 arenâ€™t much compared to prices <= 30.
Thanks once again

1 Like