python - How to delete an item in a list if it exists? -
i getting new_tag
form text field self.response.get("new_tag")
, selected_tags
checkbox fields
self.response.get_all("selected_tags")
i combine them this:
tag_string = new_tag new_tag_list = f1.striplist(tag_string.split(",") + selected_tags)
(f1.striplist
function strips white spaces inside strings in list.)
but in case tag_list
empty (no new tags entered) there selected_tags
, new_tag_list
contains empty string " "
.
for example, logging.info
:
new_tag selected_tags[u'hello', u'cool', u'glam'] new_tag_list[u'', u'hello', u'cool', u'glam']
how rid of empty string?
if there empty string in list:
>>> s = [u'', u'hello', u'cool', u'glam'] >>> = s.index("") >>> del s[i] >>> s [u'hello', u'cool', u'glam']
but if there no empty string:
>>> s = [u'hello', u'cool', u'glam'] >>> if s.index(""): = s.index("") del s[i] else: print "new_tag_list has no empty string"
but gives:
traceback (most recent call last): file "<pyshell#30>", line 1, in <module> if new_tag_list.index(""): valueerror: list.index(x): x not in list
why happen, , how work around it?
1) almost-english style:
test presence using in
operator, apply remove
method.
if thing in some_list: some_list.remove(thing)
the remove
method remove first occurrence of thing
, in order remove occurrences can use while
instead of if
.
while thing in some_list: some_list.remove(thing)
- simple enough, choice.for small lists (can't resist one-liners)
2) duck-typed, eafp style:
this shoot-first-ask-questions-last attitude common in python. instead of testing in advance if object suitable, carry out operation , 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 list!")
off course second except clause in example above not of questionable humor totally unnecessary (the point illustrate duck-typing people not familiar concept).
if expect multiple occurrences of thing:
while true: try: some_list.remove(thing) except valueerror: break
- a little verbose specific use case, idiomatic in python.
- this performs better #1
- pep 463 proposed shorter syntax try/except simple usage handy here, not approved.
however, contextlib's suppress() contextmanager (introduced in python 3.4) above code can simplified this:
with suppress(valueerror, attributeerror): some_list.remove(thing)
again, if expect multiple occurrences of thing:
with suppress(valueerror): while true: some_list.remove(thing)
3) functional style:
around 1993, python got lambda
, reduce()
, filter()
, map()
, courtesy of lisp hacker missed them , submitted working patches*. can use filter
remove elements list:
is_not_thing = lambda x: x not thing cleaned_list = filter(is_not_thing, some_list)
there shortcut may useful case: if want filter out empty items (in fact items bool(item) == false
, none
, zero, empty strings or other empty collections), can pass none first argument:
cleaned_list = filter(none, some_list)
- [update]: in python 2.x,
filter(function, iterable)
used equivalent[item item in iterable if function(item)]
(or[item item in iterable if item]
if first argumentnone
); in python 3.x, equivalent(item item in iterable if function(item))
. subtle difference filter used return list, works generator expression - ok if iterating on cleaned list , discarding it, if need list, have enclosefilter()
calllist()
constructor. - *these lispy flavored constructs considered little alien in python. around 2005, guido talking dropping
filter
- along companionsmap
,reduce
(they not gone yetreduce
moved functools module, worth if high order functions).
4) mathematical style:
list comprehensions became preferred style list manipulation in python since introduced in version 2.0 pep 202. rationale behind list comprehensions provide more concise way create lists in situations map()
, filter()
and/or nested loops used.
cleaned_list = [ x x in some_list if x not thing ]
generator expressions introduced in version 2.4 pep 289. generator expression better situations don't need (or want) have full list created in memory - when want iterate on elements 1 @ time. if iterating on list, can think of generator expression lazy evaluated list comprehension:
for item in (x x in some_list if x not thing): do_your_thing_with(item)
- see this python history blog post gvr.
- this syntax inspired set-builder notation in math.
- python 3 has set , dict comprehensions.
notes
- you may want use inequality operator
!=
instead ofis not
(the difference important) - for critics of methods implying list copy: contrary popular belief, generator expressions not more efficient list comprehensions - please profile before complaining
Comments
Post a Comment