Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Pop function for lists
#1
Hello,

I've got a two lists, one with integers and one with data and I need to remove items from the data, using the integers as index references.

For example:
 a = [1,3,4]
 b = ['a','b','c','d','e']
for i in range(len(a)):
    b.pop(a[i])
print(b)
But it comes up with errors, please help. I know there is a simple solution but I'm just not seeing it!

Thanks,
James
while dad_has_cigs == True:
    happiness = True
    if dad_has_cigs == False:
    print("Dad come home!")
    happiness = not happiness
    break
Reply
#2
a = [1,3,4]
b = ['a','b','c','d','e']
b = [i for n, i in enumerate(b) if n not in a]
print(b)
Output:
['a', 'c']
Reply
#3
Your problem is that removing an item changes the index for all items right of that item. It also reduces the size of the list. When you pop(1), b == ['a', 'c', 'd', 'e']. When you pop(3) , b == ['a', 'c', 'd'], and when you pop(4) there is no b[4].

This would work if you pop(4), pop(3), pop(1) because later pops are unaffected by previous pops.
a = [1,3,4]
a.sort(reverse=True)  # Very important the indices are in reverse order
b = ['a','b','c','d','e']
for index in a:
    b.pop(index)
print(b)
Output:
['a', 'c']
As shown by naughtyCat the more accepted method for doing something like this is to build a new list. You may look at that code and think "This is changing the original list b too, how does that work?" This is incorrect. "b" is a variable, not a list. The comprehension creates a new list and leaves the initial list unchanged. You can see that here.
a = [1,3,4]
b = ['a','b','c','d','e']
c = [i for n, i in enumerate(b) if n not in a]
print(b, c)
Output:
['a', 'b', 'c', 'd', 'e'] ['a', 'c']
In naughtyCat's example b is assigned to reference the new list. The unreferenced old list get's garbage collected.
Reply
#4
Hello,

Thanks both of you, I managed to get it fixed with the below:

 x = len(list2)
        if len(list2) > 1:
            while True:
                y = fix[x-1]
                del list[y]
                x = x - 1
                if x == 0:
                    break
while dad_has_cigs == True:
    happiness = True
    if dad_has_cigs == False:
    print("Dad come home!")
    happiness = not happiness
    break
Reply
#5
So you decided to use the approach you were advised against using. And your signature is confusing. And get off my lawn!
Reply
#6
Apologies, I had it fixed before you chaps responded. And I'll get off your lawn when you stop letting your dog do its business on mine!

Further to this I'm going through a "while True" phase at the moment. I know it's unhealthy but I can quit whenever I want to!
while dad_has_cigs == True:
    happiness = True
    if dad_has_cigs == False:
    print("Dad come home!")
    happiness = not happiness
    break
Reply
#7
Example to modify the data:

indices = [1,3,4]
data = ['a','b','c','d','e']

for index in sorted(indices, reverse=True):
    del data[index]
If you delete elements from a list, the list shrinks.
To prevent removing wrong indices, you must start with the biggest index.
If you remove an element in the middle of the list, the list shrinks by one element and all remaining elements are shifted to left.
Using this technique is very error-prone.

The Pythonic way is to create a new list instead of modifying the old list.
Example to create new data based on old data and indices:
indices = set([1,3,4]) # order doesn't matter, we want fast lookup
data = ['a','b','c','d','e']

# list comprehension
new_data = [value for index, value in enumerate(data) if index not in indices]
# only values, where the index is not in indices
# enumerate enumerates the elements and start with 0
# it's useful to work with lists
And the same with a for-loop:
indices = set([1,3,4]) # order doesn't matter, we want fast lookup
data = ['a','b','c','d','e']

new_data = []
for index, value in enumerate(data):
    if index not in indices:
        new_data.append(value)
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#8
You are right
a = [1,3,4]
b = ['a','b','c','d','e']
for index in sorted(a)[::-1]:
    b.pop(index)
Reply
#9
It turns out that treating the data in your programs as immutable values can be hugely beneficial in terms of how to think about programs - Rich Hickey has an excellent talk on this, titled The Value of Values. It's a shame that we still teach people how to program quite imperatively; most languages these days have a lot of useful abstractions that let you program more declaratively. The problem here can be expressed as: pair up each item with its index (enumerate), keep the pairs with the indices that you want (filter) and then from each pair, select only the items (map). The list comprehension shown above neatly expresses that. Kevlin Henney has a great talk on programming declaratively, titled Declarative Thinking, Declarative Practice and the Toolz library provides a set of functions to help programming that way, beyond what's in the standard library.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Use ranking function for different lists klatlap 6 1,966 Feb-15-2022, 11:31 PM
Last Post: klatlap
  Split dict of lists into smaller dicts of lists. pcs3rd 3 2,312 Sep-19-2020, 09:12 AM
Last Post: ibreeden
  Reading Multiple Lists Using SUM function dgrunwal 6 3,285 Jun-03-2020, 08:23 PM
Last Post: dgrunwal
  Money conversion - problems with lists and .format function fatherted99 1 1,783 Mar-12-2020, 06:29 PM
Last Post: ndc85430
  Using function argument in lists comprehension. blackknite 5 3,012 Apr-23-2019, 09:59 PM
Last Post: snippsat
  sort lists of lists with multiple criteria: similar values need to be treated equal stillsen 2 3,190 Mar-20-2019, 08:01 PM
Last Post: stillsen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020