How to delete an item in a list if it exists?

前端 未结 7 938
無奈伤痛
無奈伤痛 2020-11-29 14:55

I am getting new_tag from a form text field with self.response.get(\"new_tag\") and selected_tags from checkbox fields with



        
7条回答
  •  执念已碎
    2020-11-29 15:20

    1) Almost-English style:

    Test for presence using the in operator, then apply the remove method.

    if thing in some_list: some_list.remove(thing)
    

    The removemethod will remove only the first occurrence of thing, in order to remove all occurrences you can use while instead of if.

    while thing in some_list: some_list.remove(thing)    
    
    • Simple enough, probably my choice.for small lists (can't resist one-liners)

    2) Duck-typed, EAFP style:

    This shoot-first-ask-questions-last attitude is common in Python. Instead of testing in advance if the object is suitable, just carry out the operation and catch relevant Exceptions:

    try:
        some_list.remove(thing)
    except ValueError:
        pass # or scream: thing not in some_list!
    except AttributeError:
        call_security("some_list not quacking like a list!")
    

    Off course the second except clause in the example above is not only of questionable humor but totally unnecessary (the point was to illustrate duck-typing for people not familiar with the concept).

    If you expect multiple occurrences of thing:

    while True:
        try:
            some_list.remove(thing)
        except ValueError:
            break
    
    • a little verbose for this specific use case, but very idiomatic in Python.
    • this performs better than #1
    • PEP 463 proposed a shorter syntax for try/except simple usage that would be handy here, but it was not approved.

    However, with contextlib's suppress() contextmanager (introduced in python 3.4) the above code can be simplified to this:

    with suppress(ValueError, AttributeError):
        some_list.remove(thing)
    

    Again, if you expect multiple occurrences of thing:

    with suppress(ValueError):
        while True:
            some_list.remove(thing)
    

    3) Functional style:

    Around 1993, Python got lambda, reduce(), filter() and map(), courtesy of a Lisp hacker who missed them and submitted working patches*. You can use filter to remove elements from the list:

    is_not_thing = lambda x: x is not thing
    cleaned_list = filter(is_not_thing, some_list)
    

    There is a shortcut that may be useful for your case: if you want to filter out empty items (in fact items where bool(item) == False, like None, zero, empty strings or other empty collections), you can pass None as the first argument:

    cleaned_list = filter(None, some_list)
    
    • [update]: in Python 2.x, filter(function, iterable) used to be equivalent to [item for item in iterable if function(item)] (or [item for item in iterable if item] if the first argument is None); in Python 3.x, it is now equivalent to (item for item in iterable if function(item)). The subtle difference is that filter used to return a list, now it works like a generator expression - this is OK if you are only iterating over the cleaned list and discarding it, but if you really need a list, you have to enclose the filter() call with the list() constructor.
    • *These Lispy flavored constructs are considered a little alien in Python. Around 2005, Guido was even talking about dropping filter - along with companions map and reduce (they are not gone yet but reduce was moved into the functools module, which is worth a look if you like high order functions).

    4) Mathematical style:

    List comprehensions became the preferred style for list manipulation in Python since introduced in version 2.0 by PEP 202. The rationale behind it is that List comprehensions provide a more concise way to create lists in situations where map() and filter() and/or nested loops would currently be used.

    cleaned_list = [ x for x in some_list if x is not thing ]
    

    Generator expressions were introduced in version 2.4 by PEP 289. A generator expression is better for situations where you don't really need (or want) to have a full list created in memory - like when you just want to iterate over the elements one at a time. If you are only iterating over the list, you can think of a generator expression as a lazy evaluated list comprehension:

    for item in (x for x in some_list if x is not thing):
        do_your_thing_with(item)
    
    • See this Python history blog post by GvR.
    • This syntax is inspired by the set-builder notation in math.
    • Python 3 has also set and dict comprehensions.

    Notes

    1. you may want to use the inequality operator != instead of is not (the difference is important)
    2. for critics of methods implying a list copy: contrary to popular belief, generator expressions are not always more efficient than list comprehensions - please profile before complaining

提交回复
热议问题