How to remove an item from a list but keep original indices in Python

Question:

So basically in my program after a certain criteria is not met for an item in my list i take it out and then run it through an algorithm to check if that item being taken out affects the rest of the items in the list.
My problem however is that when i take out this item it pushes back all my other list items back 1 index so when i go to check if it affects the other items using my algorithm it messes up since the indexes are changing constantly over the iterating of the for loop. This is my code and I will show an example of the run:

    for l in range(len(assets)-1):
    print("The current unsafe banks are:",unsafe)
    print("Current assets of the banks which are not yet in unsafe list:")
    for h in range(len(assets)):
            print("Bank ", h ," Current assets: ",assets[h]," millions.")
    print()
    for i in range(len(assets)-1):
        if(assets[i]<=limit):
            print("Adding Bank:", i," to the list of unsafe banks.")
            unsafe.append(i)
            assets.remove(assets[i])
            banks.remove(banks[i])
            i=float(i)
            for j in range(len(banks)):
                for k in range(len(banks[j])-1):
                    if i == banks[j][k]:
                        banks[j][k+1]=0
            assets=current_Assets(banks)
            print(banks)    

My questions is how do i make it so the list keeps the original indexes of the items after I remove and item from it instead of pushing it back. Thank you.

Example run:

Current assets of the banks which are not yet in unsafe list:

Bank  0  Current assets:  446.0  millions.
Bank  1  Current assets:  250.0  millions.
Bank  2  Current assets:  269.0  millions.
Bank  3  Current assets:  200.0  millions.
Bank  4  Current assets:  375.0  millions.
Bank  5  Current assets:  250.0  millions.
Bank  6  Current assets:  280.0  millions.

Adding Bank: 3  to the list of unsafe banks.

[
    [25.0, 1.0, 100.5, 4.0, 320.5],
    [125.0, 2.0, 40.0, 3.0, 0],
    [69.0, 0.0, 125.0, 3.0, 0],
    [250.0, 2.0, 125.0],
    [100.0, 0.0, 80.0, 4.0, 70.0],
    [150.0, 1.0, 10.0, 2.0, 80.0, 3.0, 0]
]
The current unsafe banks are: [3]
Current assets of the banks which are not yet in unsafe list:
Bank  0  Current assets:  446.0  millions.
Bank  1  Current assets:  165.0  millions.
Bank  2  Current assets:  194.0  millions.
Bank  3  Current assets:  375.0  millions.
Bank  4  Current assets:  250.0  millions.
Bank  5  Current assets:  240.0  millions.

As you can see it pushes Bank 4 back to Bank 3.

Asked By: ZarifS

||

Answers:

List indexes are always 0 to len(lst) - 1. So when you remove an item from the list, len(lst) decreases by one and all indices after the item you removed update. There is no way to change this behavior; it is totally by design, so you can iterate properly over a list’s items.

If you need static indexes, then you should look at dictionaries. There, you can use whatever key you want, including numbers, so if you remove an item from the dictionary, it is just removed but does not affect the other ones. A key just disappeared.

>>> banks = {
        0: 'bank 0',
        1: 'bank 1',
        2: 'bank 2',
        3: 'bank 3'
    }
>>> banks
{0: 'bank 0', 1: 'bank 1', 2: 'bank 2', 3: 'bank 3'}
>>> del banks[2] # remove bank 2
>>> banks
{0: 'bank 0', 1: 'bank 1', 3: 'bank 3'}
Answered By: poke

When working on iterators like lists, it is best not to mess with the iterator, as you are experiencing. A copy of the iterator should be made and it should be used used within your loop.
So at the beginning of your loop there should be something like:

assets_copy = assets.copy()

and any append or removes withing the loop should be done on the copy.

Answered By: Carl Hoffmann

I would suggest using a dict and/or class instead. Here is how you could set up a basic class to create “banks”:

class bank():
    def __init__(self, name):
        self.name = name
        self.currentAssets = 0
        self.safe = True

def foo()
    limit = 275.0   # some arbitrary threshold, modify as needed
    # Initialize your list of banks:        
    banks = [bank('Bank ' + str(i)) for i in range(7)]
    # assign their properties
    # you may be reading this from a stream or another input, modify as needed
    banks[0].currentAssets = 446.0
    banks[1].currentAssets = 250.0
    banks[2].currentAssets = 269.0
    banks[3].currentAssets = 200.0
    banks[4].currentAssets = 375.0
    banks[5].currentAssets = 250.0
    banks[6].currentAssets = 280.0

    # flag the unsafe banks:
    for b in banks:
        b.safe = (b.currentAssets < limit)

        if b.safe:
            # do something to the 'safe' banks
        else:
            print '{} is unsafe with assets: {} millions which is less than the limit of {}'.format(b[i].name, b.currentAssets, limit)

    # etc...
Answered By: David Zemens

there are some ways, but they make code more ugly

you can try this

**remo_ve = []  #** 
for i in range(len(assets)-1):
    if(assets[i]<=limit):
        print("Adding Bank:", i," to the list of unsafe banks.")
        unsafe.append(i)
        **remo_ve.append(i)**
        #assets.remove(assets[i])
        #banks.remove(banks[i])
        i=float(i)
        for j in range(len(banks)):
            for k in range(len(banks[j])-1):
                if i == banks[j][k]:
                    banks[j][k+1]=0
        assets=current_Assets(banks)
        print(banks)    
**for i in remo_ve:
        assets.remove(assets[i])
        banks.remove(banks[i])**

or you can use unsafe list, so dont need to add a new list variable

Answered By: lam vu Nguyen
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.