如何删除列表中的项目(如果存在)?
我正在从带有self.response.get("new_tag")
的表单文本字段中获取new_tag
,并从带有
I am getting new_tag
from a form text field with self.response.get("new_tag")
and selected_tags
from checkbox fields with
self.response.get_all("selected_tags")
我这样合并它们:
tag_string = new_tag
new_tag_list = f1.striplist(tag_string.split(",") + selected_tags)
(f1.striplist
是在列表中的字符串内去除空格的函数.)
(f1.striplist
is a function that strips white spaces inside the strings in the list.)
但是如果tag_list
为空(没有输入新标签)但有一些selected_tags
,则new_tag_list
包含一个空字符串" "
.
But in the case that tag_list
is empty (no new tags are entered) but there are some selected_tags
, new_tag_list
contains an empty string " "
.
例如,来自logging.info
:
new_tag
selected_tags[u'Hello', u'Cool', u'Glam']
new_tag_list[u'', u'Hello', u'Cool', u'Glam']
如何摆脱空字符串?
如果列表中有一个空字符串:
If there is an empty string in the list:
>>> s = [u'', u'Hello', u'Cool', u'Glam']
>>> i = s.index("")
>>> del s[i]
>>> s
[u'Hello', u'Cool', u'Glam']
但是如果没有空字符串:
But if there is no empty string:
>>> s = [u'Hello', u'Cool', u'Glam']
>>> if s.index(""):
i = s.index("")
del s[i]
else:
print "new_tag_list has no empty string"
但这给出了:
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 does this happen, and how do I work around it?
1)几乎是英语风格:
使用in
运算符测试是否存在,然后应用remove
方法.
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)
remove
方法将仅删除第一次出现的thing
,要删除所有出现的内容,可以使用while
而不是if
.
The remove
method 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)
- 足够简单,可能是我的选择.对于小的清单(无法抗拒一线)
这种先射击后问问题的态度在Python中很常见.无需预先测试对象是否合适,只需执行操作并捕获相关的异常即可:
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!")
当然,上面示例中的第二个except子句不仅具有可疑的幽默感,而且完全没有必要(重点是为不熟悉该概念的人说明鸭子式输入法.)
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
- 此特定用例有点冗长,但在Python中非常惯用.
- 这比#1表现更好
- PEP 463 针对try/提出了一种较短的语法,但简单用法除外在这里会很方便,但是没有被批准.
- 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.
但是,使用 contextlib的prevent()contextmanager (已引入在python 3.4中),上述代码可以简化为:
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)功能风格:
在1993年左右,Python得到lambda
,reduce()
,filter()
和map()
,由 Lisp 黑客,他们错过了他们并提交了有效的补丁程序*.您可以使用filter
从列表中删除元素:
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)
有一个捷径可能对您的情况有用:如果您想过滤出空项目(实际上是bool(item) == False
的项目,例如None
,零,空字符串或其他空集合),则可以传递无作为第一个参数:
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)
- [更新] :在Python 2.x中,
filter(function, iterable)
以前等同于[item for item in iterable if function(item)]
(如果第一个参数为None
,则为[item for item in iterable if item]
);在Python 3.x中,它现在等效于(item for item in iterable if function(item))
.细微的区别是过滤器用于返回列表,现在它像生成器表达式一样工作-如果仅遍历已清理的列表并将其丢弃,则可以,但是如果您确实需要列表,则必须将filter()
使用list()
构造函数调用. - *这些Lispy风格的构造在Python中被认为有点陌生.在2005年左右, Guido甚至在谈论删除
filter
-以及同伴map
和reduce
(它们尚未消失,但reduce
已移入 functools 模块,如果您喜欢高级功能,则值得一看). -
[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 isNone
); 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 thefilter()
call with thelist()
constructor. - *These Lispy flavored constructs are considered a little alien in Python. Around 2005, Guido was even talking about dropping
filter
- along with companionsmap
andreduce
(they are not gone yet butreduce
was moved into the functools module, which is worth a look if you like high order functions).
列表理解成为Python中列表处理的首选样式,因为 PEP 202 .其背后的理由是,列表推导提供了一种更简洁的方法,可以在当前将使用map()
和filter()
和/或嵌套循环的情况下创建列表.
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 ]
生成器表达式是在2.4版中由 PEP 289 引入的.对于实际上不需要(或不想)在内存中创建完整列表的情况(例如,您只想一次遍历一个元素的情况),生成器表达式是更好的选择.如果仅遍历列表,则可以将生成器表达式视为惰性求值列表理解力:
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)
- 请参见此Python历史博客由 GvR 发布.
- 此语法的灵感来自数学中的 set-builder标记. >
- Python 3还具有 set 和
- 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.
- 您可能要使用不等式运算符
!=
而不是is not
(区别很重要) - 对于暗示要使用列表副本的方法的批评者:与普遍的看法相反,生成器表达式并不总是比列表理解更有效-请在抱怨之前进行简要介绍
- you may want to use the inequality operator
!=
instead ofis not
(the difference is important) - 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