Python Forum
removing one list element without using its index
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
removing one list element without using its index
#1
Hi

This is very naïve, but i'm wondering if there's a more relevant way to remove an element from a list?

Thanks

myList = [5, 30, 100, 10]
val2Remove = 100

myList_to_str = [str(elem) for elem in myList]
str_val = str(val2Remove)

myList_to_str.remove(str_val)
myList = [int(elem) for elem in myList_to_str]
Reply
#2
  • the names are not pythonic
  • use the method remove to remove items from the list
  • if an item is not in the list and you use the method remove, then a ValueError is thrown. You can catch this exception.

my_list = [5, 30, 100, 10]
remove_val = 100

try:
    my_list.remove(remove_val)
except ValueError:
    print(remove_val, "not found")
else:
    print(remove_val, "has been removed once.")
But if 100 is more than once in the list, this code above removes only the first occurring 100.
Then it's easier to create a new list:

my_list = [100, 5, 30, 100, 10, 100]
remove_val = 100

new_list = [value for value in my_list if value != remove_val]
This code does not throw an exception, if 100 is not in the list at all.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#3
Internally, Python lists are integer indexed dynamic arrays. Here is an interesting, if old, question and interesting answers and links on stackoverflow.

There is quite a lot going on behind the scenes when you add or delete elements!

As I understand it, you cannot access the values in a list without using the pointer variables, the index, which tells us where they are in memory and what kind of value is stored there.

So, if my_list.remove(3) seems to get rid of 3 without using its index, that is only superficially so.

I don't know how .remove() works internally, but you can fake it like this:

def remove_it(val, alist):
    for i in range(len(alist)):
        if alist[i] == val:
            alist.pop(i)
            return alist

my_list = [1, 2, 3, 4, 5]
remove_it(3, my_list)
Output:
[1, 2, 4, 5]
Or like this:

def remove_it(val, alist):
    for i in range(len(alist)):
        if alist[i] == val:
            del alist[i]
            return alist

my_list = [1, 2, 3, 4, 5]
remove_it(3, my_list)
Output:
[1, 2, 4, 5]
Reply
#4
Your code example is wrong.
  • Indentation of return
  • the use of range(len(element)), iterate directly
  • alist is modified in-place and is also returned
  • Iterating over a list and modifying the list in-place will throw an IndexError.

If you change then indentation to iterate over all elements, then you would get an IndexError.

This modifies the list in-place and does return None:
def remove_it(val, alist):
    remove = []

    for index, element in enumerate(alist):
        if element == val:
            remove.append(index)
    
    for index in reversed(remove):
        alist.pop(index)


my_list = [3, 1, 2, 3, 4, 5, 3]

print(my_list)
remove_it(3, my_list)
print(my_list)
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#5
Entspann dich Alter, das hier ist nicht die Prüfung zum Pythonmeister des Jahres! War nur 'ne Vermutung darauf wie .remove(3) eventuell seine Wunder wirkt!

Quote:Indentation of return:
if return was not so indented, an IndexError would surface. As it is it works.

Quote:the use of range(len(element)), iterate directly:
not sure what you mean here; type(len(mylist)) returns: <class 'int'> I think it is OK to range(int).

Quote:alist is modified in-place and is also returned:
alist is passed to the function. LEGB means, the function looks first Locally and finds alist. In effect, it is a copy of alist.

Quote:Iterating over a list and modifying the list in-place will throw an IndexError.:
Not necessarily. Try the function remove_it(val, alist), let me know if you get an IndexError.

mylist.remove(3) only removes 1 instance of 3.

Quote:But if 100 is more than once in the list, this code above removes only the first occurring 100.

I'm sure it is possible to alter remove_it() to eliminate all instances of val. I wasn't aware that was the goal! That is not the way .remove() works.

Ist es nicht anstrengend, immer humorlos und streng zu sein? Lighten up a little ja?
Reply
#6
Iterating over a list and modifying it at the same time is never a good idea, as it can lead to obvious to weird errors. Or, to put it short: simply never do it. It's an absolute anti-pattern.

Regards, noisefloor
Reply
#7
Quote:Iterating over a list and modifying it at the same time is never a good idea, as it can lead to obvious to weird errors. Or, to put it short: simply never do it. It's an absolute anti-pattern.

Sure, if you wish to keep iterating. CPython ob_size is reallocated.

The problem arises, maybe not immediately, when you continue iterating to an index value that is no longer present in the list. But, if you leave the loop when you find what you want, you will never have this problem!

You don't need the function remove_it(val, alist) below, Python already has .remove(val). I was just wondering how .remove(val) works.

Rules can be helpful, but rules may also be, and often are, broken.

From the link I posted above:

Quote:The C code is pretty simple, actually. Expanding one macro and pruning some irrelevant comments, the basic structure is in listobject.h, which defines a list as:

typedef struct {
PyObject_HEAD
Py_ssize_t ob_size;

/* Vector of pointers to list elements. list[0] is ob_item[0], etc. */
PyObject **ob_item;

/* ob_item contains space for 'allocated' elements. The number
* currently in use is ob_size.
* Invariants:
* 0 <= ob_size <= allocated
* len(list) == ob_size
* ob_item == NULL implies ob_size == allocated == 0
*/
Py_ssize_t allocated;
} PyListObject;
PyObject_HEAD contains a reference count and a type identifier. So, it's a vector/array that overallocates. The code for resizing such an array when it's full is in listobject.c. It doesn't actually double the array, but grows by allocating

You can see, behind the scenes, unseen by the Python user, there is a lot going on!

If you want to get rid of all instances of val in a list, the following, rule-breaking, code works without error. This is just for simulating what I think .remove(val) does.

def remove_it(val, alist):    
    for i in range(len(alist)):
        if alist[i] == val:
            del alist[i]                     
            return alist 
      
my_list = [3, 1, 2, 3, 4, 5, 3, 3]

while not remove_it(3, my_list) is None:
    if type(remove_it(3, my_list)) == 'list': 
        my_list = remove_it(3, my_list)
Output:
my_list: [1, 2, 4, 5]
Reply
#8
(Feb-21-2025, 04:05 PM)Pedroski55 Wrote: Entspann dich Alter, das hier ist nicht die Prüfung zum Pythonmeister des Jahres! War nur 'ne Vermutung darauf wie .remove(3) eventuell seine Wunder wirkt!

Ich bin nicht dein "Alter"!

Du zeigst Anfängern den falschen Weg. Des Weiteren führen Vermutungen beim Programmieren immer zu unerwarteten Ergebnissen. Dein Beispiel kann als Negativ-Beispiel dienen, wie man es nicht machen solle. Ja, auch das sollte man lernen.

Quote:Note: Never change the object to be iterated during an iteration.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  question about changing the string value of a list element jacksfrustration 4 2,170 Feb-08-2025, 07:43 AM
Last Post: jacksfrustration
  extract an element of a list into a string alexs 5 3,823 Aug-30-2024, 09:24 PM
Last Post: alexs
  element in list detection problem jacksfrustration 5 1,894 Apr-11-2024, 05:44 PM
Last Post: deanhystad
  Variable for the value element in the index function?? Learner1 8 2,997 Jan-20-2024, 09:20 PM
Last Post: Learner1
  list in dicitonary element problem jacksfrustration 3 1,666 Oct-14-2023, 03:37 PM
Last Post: deanhystad
Thumbs Down I hate "List index out of range" Melen 20 9,133 May-14-2023, 06:43 AM
Last Post: deanhystad
  Find (each) element from a list in a file tester_V 3 2,245 Nov-15-2022, 08:40 PM
Last Post: tester_V
  Сheck if an element from a list is in another list that contains a namedtuple elnk 8 3,473 Oct-26-2022, 04:03 PM
Last Post: deanhystad
  IndexError: list index out of range dolac 4 3,394 Jul-25-2022, 03:42 PM
Last Post: deanhystad
  Membership test for an element in a list that is a dict value for a particular key? Mark17 2 2,023 Jul-01-2022, 10:52 PM
Last Post: Pedroski55

Forum Jump:

User Panel Messages

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