On line 15 when you print the new prices, you will see:
New Prices: [25, 20, 35, 15, 15, 30, 45, 30]
As noted by ktsotras, when your loop (on line 18) finishes, then i
will hold the last value assigned to it.
After the last iteration of the loop for i in range(len(hairstyles))
, the last value assigned to i
will be 7
.
# My initial code: what's wrong here?
cuts_under_30 = [hairstyles[i] for new_prices[i] in new_prices if new_prices[i] < 30]
print(cuts_under_30)
In your list comprehension above, you are iterating over the new_prices
list but the loop variable chosen by you is new_prices[i]
.
In the first iteration, the first element of new_prices
i.e. 25
will be assigned to new_prices[i]
which is equivalent to the assignment new_prices[7] = 25
. Then the if condition, checks whether new_prices[7] < 30
. If so, hairstyles[i]
i.e. hairstyles[7]
is appended to the cuts_under_30
list. There are four values in new_prices
which are less than 30
, so hairstyles[7]
i.e. the string "flattop"
will be appended to cuts_under_30
four times. Consequently, the output seen by you will be:
['flattop', 'flattop', 'flattop', 'flattop']
To better understand what is going on, try turning your list comprehension into a for loop (with print statements for debugging):
print(new_prices)
cuts_under_30 = []
for new_prices[i] in new_prices:
print(new_prices)
if new_prices[i] < 30:
cuts_under_30.append(hairstyles[i])
print(cuts_under_30)
// Output
// new_prices before loop
[25, 20, 35, 15, 15, 30, 45, 30]
// new_prices during loop
// Note what is happening to new_prices[7]
[25, 20, 35, 15, 15, 30, 45, 25]
[25, 20, 35, 15, 15, 30, 45, 20]
[25, 20, 35, 15, 15, 30, 45, 35]
[25, 20, 35, 15, 15, 30, 45, 15]
[25, 20, 35, 15, 15, 30, 45, 15]
[25, 20, 35, 15, 15, 30, 45, 30]
[25, 20, 35, 15, 15, 30, 45, 45]
[25, 20, 35, 15, 15, 30, 45, 45]
// cuts_under_30 after loop
['flattop', 'flattop', 'flattop', 'flattop']
Both your use of i
and the choice of new_prices[i]
as the loop variable is problematic.
You could use a variable such as
for price in new_prices:
This will iterate over new_prices
properly, but the problem is that the hairstyles are in a different list, and just the price won’t allow you to pick out the corresponding hairstyle.
Instead, looping over the index as you did in
# Revised:
cuts_under_30 = [hairstyles[i] for i in range(len(new_prices)) if new_prices[i] < 30]
works. By looping over the index, you can use the same index i
to pair the price with the corresponding hairstyle by targeting the correct elements from the new_prices
and hairstyles
lists respectively.