How to enumerate over a list in python backwards with index(From the end to the beginning)

Viewed 1872

I'm like to iterate over a list of received data from Digikey api any didn't have much luck googling since the function enumerate(reversed(part.standard_pricing)) just doesn't work and you can't reverse the part.standard_pricing for some reason Something like that is desired:

for b_idx in range(part.standard_pricing, -1, -1):
            print(f"Test at: {b_idx} , Q: {part.standard_pricing[b_idx].break_quantity}")
            if PCountQ >= part.standard_pricing[b_idx].break_quantity:
                parts_df['PRICE_PER_PCB_Q'][idx] = part.standard_pricing[b_idx].unit_price * PCountQ
                break

But range doesn't work on list either...

I'd like to do that:

for b_idx, price_break in enumerate(part.standard_pricing):

just instead start from the end of part.standard_pricing and have the index decrease instead of increase

Any idea on how to do that pythonically?

3 Answers

You can call enumerate on the list, then convert the enumerate object to list, it will give list of tuples where each tuple will have index and value, finally iterate on reversed list.

data = [1,2,3,4]
for i,d in reversed(list(enumerate(data))):
    print(i,d)
    
3 4
2 3
1 2
0 1

In case, you don't want another copy of the sequence in the memory, you can create your custom generator.

def reverseEnum(data: list):
    for i in range(len(data)-1, -1, -1):
        yield (i, data[i])
for i, d in reverseEnum([1, 2, 3, 4]):
    print(i, d)
    
3 4
2 3
1 2
0 1

Instead of reverseing the enumerated list, we can also enumerate the reversed list and use a bit of math for the index:

the_list = ["zeroth", "first", "second"]
length = len(the_list)

for j, value in enumerate(reversed(the_list), start=1):
    # "the" index is this
    i = length - j
    print(i, value)

to get

2 second
1 first
0 zeroth

You can also go for i = -j and get -1, -2, -3, which, when indexes, gives the same values as the 2, 1, 0 respectively.

You don't need to reverse or copy the list. Just use it in place and index it from the end:

for b_idx in range(len(part.standard_pricing)-1, -1, -1):
    print(f"Test at: {b_idx} , Q: {part.standard_pricing[b_idx].break_quantity}")

This is a mirror of the Python antipattern

    for b_idx in range(len(part.standard_pricing)):

but since it is a mirror you can consider it an anti-antipattern.

Related