Python 如何删除列表中的项目(如果存在)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4915920/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to delete an item in a list if it exists?
提问by Zeynel
I am getting new_tagfrom a form text field with self.response.get("new_tag")and selected_tagsfrom checkbox fields with
我new_tag从表单文本字段self.response.get("new_tag")和selected_tags复选框字段中获取
self.response.get_all("selected_tags")
I combine them like this:
我把它们组合成这样:
tag_string = new_tag
new_tag_list = f1.striplist(tag_string.split(",") + selected_tags)
(f1.striplistis a function that strips white spaces inside the strings in the list.)
(f1.striplist是一个去除列表中字符串内空格的函数。)
But in the case that tag_listis empty (no new tags are entered) but there are some selected_tags, new_tag_listcontains an empty string " ".
但是在tag_list为空的情况下(没有输入新标签)但有一些selected_tags,new_tag_list包含一个空字符串" "。
For example, from logging.info:
例如,来自logging.info:
new_tag
selected_tags[u'Hello', u'Cool', u'Glam']
new_tag_list[u'', u'Hello', u'Cool', u'Glam']
How do I get rid of the empty string?
如何摆脱空字符串?
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"
But this 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 does this happen, and how do I work around it?
为什么会发生这种情况,我该如何解决?
采纳答案by Paulo Scardine
1) Almost-English style:
1)近乎英式风格:
Test for presence using the inoperator, then apply the removemethod.
使用in运算符测试是否存在,然后应用该remove方法。
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 whileinstead of if.
该remove方法将仅删除第一次出现的thing,以便删除您可以使用while代替 的所有出现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, EAFPstyle:
2)鸭式,EAFP风格:
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:
这种先拍后问的态度在 Python 中很常见。无需提前测试对象是否合适,只需执行操作并捕获相关异常即可:
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).
当然,上面例子中的第二个 except 子句不仅幽默有问题,而且完全没有必要(重点是为不熟悉这个概念的人说明鸭子类型)。
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 463proposed a shorter syntax for try/except simple usage that would be handy here, but it was not approved.
- 这个特定用例有点冗长,但在 Python 中非常惯用。
- 这比 #1 表现更好
- PEP 463为 try/except 简单用法提出了更短的语法,这在此处很方便,但未获批准。
However, with contextlib's suppress() contextmanager(introduced in python 3.4) the above code can be simplified to this:
然而,使用contextlib 的suppress() 上下文管理器(在python 3.4 中引入),上面的代码可以简化为:
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:
3)功能风格:
Around 1993, Python got lambda, reduce(), filter()and map(), courtesy of a Lisphacker who missed them and submitted working patches*. You can use filterto remove elements from the list:
1993年左右,巨蟒有lambda,reduce(),filter()和map(),一个礼貌的Lisp黑客谁错过了他们,并提交工作补丁*。您可以使用filter从列表中删除元素:
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:
有一个快捷方式可能对您的情况有用:如果您想过滤掉空项目(实际上是项目 where bool(item) == False,如None,零,空字符串或其他空集合),您可以将 None 作为第一个参数传递:
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 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 companionsmapandreduce(they are not gone yet butreducewas moved into the functoolsmodule, which is worth a look if you like high order functions).
- [更新]:在 Python 2.x 中,
filter(function, iterable)曾经等价于[item for item in iterable if function(item)](或者[item for item in iterable if item]如果第一个参数是None);在 Python 3.x 中,它现在等效于(item for item in iterable if function(item)). 细微的区别是过滤器用于返回列表,现在它像生成器表达式一样工作 - 如果您只是遍历清理过的列表并丢弃它,这是可以的,但是如果您确实需要一个列表,则必须包含filter()调用与list()构造函数。 - *这些 Lispy 风格的构造在 Python 中被认为有点陌生。大约在 2005 年,Guido 甚至在谈论删除
filter- 以及同伴map和reduce(他们还没有消失,但reduce被移入了functools模块,如果你喜欢高阶函数,值得一看)。
4) Mathematical style:
4)数学风格:
List comprehensionsbecame 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.
列表内涵成为在Python列表操作的首选风格,因为在2.0版本中引入PEP 202。其背后的理由是,列表解析提供了更简洁的方式来创建情况列表,其中map()和filter()和/或嵌套循环将目前被使用。
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 evaluatedlist comprehension:
生成器表达式是由PEP 289在 2.4 版中引入的。生成器表达式更适合您并不真正需要(或不想)在内存中创建完整列表的情况——比如您只想一次迭代一个元素。如果您只是迭代列表,您可以将生成器表达式视为惰性求值的列表推导式:
for item in (x for x in some_list if x is not thing):
do_your_thing_with(item)
- See this Python history blogpost by GvR.
- This syntax is inspired by the set-builder notationin math.
- Python 3 has also setand dict comprehensions.
- 请参阅GvR 的这篇 Python 历史博客文章。
- 这种语法的灵感来自数学中的set-builder 符号。
- Python 3 也有set和dict comprehensions。
Notes
笔记
- 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
- 您可能想要使用不等式运算符
!=而不是is not(差异很重要) - 对于暗示列表副本的方法的批评者:与流行的看法相反,生成器表达式并不总是比列表理解更有效 - 请在抱怨之前进行分析
回答by phihag
If indexdoesn't find the searched string, it throws the ValueErroryou're seeing. Either
catch the ValueError:
如果index没有找到搜索到的字符串,它会抛出ValueError你看到的。要么捕获 ValueError:
try:
i = s.index("")
del s[i]
except ValueError:
print "new_tag_list has no empty string"
oruse find, which returns -1 in that case.
或使用find,在这种情况下返回 -1。
i = s.find("")
if i >= 0:
del s[i]
else:
print "new_tag_list has no empty string"
回答by Tim Pietzcker
try:
s.remove("")
except ValueError:
print "new_tag_list has no empty string"
Note that this will only remove one instance of the empty string from your list (as your code would have, too). Can your list contain more than one?
请注意,这只会从您的列表中删除空字符串的一个实例(您的代码也是如此)。您的列表可以包含多个吗?
回答by dfichter
Eek, don't do anything that complicated : )
哎呀,不要做任何复杂的事情:)
Just filter()your tags. bool()returns Falsefor empty strings, so instead of
只是filter()你的标签。 bool()返回False空字符串,而不是
new_tag_list = f1.striplist(tag_string.split(",") + selected_tags)
you should write
你应该写
new_tag_list = filter(bool, f1.striplist(tag_string.split(",") + selected_tags))
or better yet, put this logic inside striplist()so that it doesn't return empty strings in the first place.
或者更好的是,把这个逻辑放在里面,striplist()这样它就不会首先返回空字符串。
回答by Dane White
Here's another one-liner approach to throw out there:
这是另一种单线方法扔在那里:
next((some_list.pop(i) for i, l in enumerate(some_list) if l == thing), None)
It doesn't create a list copy, doesn't make multiple passes through the list, doesn't require additional exception handling, and returns the matched object or None if there isn't a match. Only issue is that it makes for a long statement.
它不会创建列表副本,不会多次遍历列表,不需要额外的异常处理,并且如果没有匹配则返回匹配的对象或 None。唯一的问题是它是一个很长的声明。
In general, when looking for a one-liner solution that doesn't throw exceptions, next() is the way to go, since it's one of the few Python functions that supports a default argument.
通常,在寻找不抛出异常的单行解决方案时,next() 是最佳选择,因为它是少数支持默认参数的 Python 函数之一。
回答by ideasman42
Adding this answer for completeness, though it's only usable under certain conditions.
添加此答案是为了完整性,尽管它仅在某些条件下可用。
If you have very large lists, removing from the end of the list avoids CPython internals having to memmove, for situations where you can re-order the list. It gives a performance gain to remove from the end of the list, since it won't need to memmoveeveryitem after the one your removing - back one step (1).
For one-off removals the performance difference may be acceptable, but if you have a large list and need to remove many items - you will likely notice a performance hit.
如果您有非常大的列表,从列表的末尾删除可以避免 CPython 内部必须memmove重新排序列表的情况。它提供了从列表末尾删除的性能提升,因为它不需要在您删除后的memmove每个项目 - 后退一步(1)。
对于一次性删除,性能差异可能是可以接受的,但如果您有一个很大的列表并且需要删除许多项目 - 您可能会注意到性能下降。
Although admittedly, in these cases, doing a full list search is likely to be a performance bottleneck too, unless items are mostly at the front of the list.
尽管不可否认,在这些情况下,执行完整列表搜索也可能是性能瓶颈,除非项目大部分位于列表的前面。
This method can be used for more efficient removal,
as long as re-ordering the list is acceptable. (2)
只要对列表重新排序是可以接受的,就可以使用此方法进行更有效的删除。(2)
def remove_unordered(ls, item):
i = ls.index(item)
ls[-1], ls[i] = ls[i], ls[-1]
ls.pop()
You may want to avoid raising an error when the itemisn't in the list.
当item不在列表中时,您可能希望避免引发错误。
def remove_unordered_test(ls, item):
try:
i = ls.index(item)
except ValueError:
return False
ls[-1], ls[i] = ls[i], ls[-1]
ls.pop()
return True
- While I tested this with CPython, its quite likely most/all other Python implementations use an array to store lists internally. So unless they use a sophisticated data structure designed for efficient list re-sizing, they likely have the same performance characteristic.
- 虽然我用 CPython 对此进行了测试,但很可能大多数/所有其他 Python 实现都使用数组在内部存储列表。因此,除非他们使用专为有效调整列表大小而设计的复杂数据结构,否则他们可能具有相同的性能特征。
A simple way to test this, compare the speed difference from removing from the front of the list with removing the last element:
python -m timeit 'a = [0] * 100000' 'while a: a.remove(0)'With:
python -m timeit 'a = [0] * 100000' 'while a: a.pop()'(gives an order of magnitude speed difference where the second example is faster with CPython and PyPy).
一个简单的测试方法,比较从列表前面删除与删除最后一个元素的速度差异:
python -m timeit 'a = [0] * 100000' 'while a: a.remove(0)'和:
python -m timeit 'a = [0] * 100000' 'while a: a.pop()'(给出一个数量级的速度差异,其中第二个示例使用 CPython 和 PyPy 更快)。
- In this case you might consider using a
set, especially if the list isn't meant to store duplicates.
In practice though you may need to store mutable data which can't be added to aset. Also check on btree's if the data can be ordered.
- 在这种情况下,您可以考虑使用
set,尤其是在列表不打算存储重复项的情况下。
在实践中,尽管您可能需要存储无法添加到set. 还要检查 btree 是否可以订购数据。
回答by SollyBunny
All you have to do is this
你所要做的就是这个
list = ["a", "b", "c"]
try:
list.remove("a")
except:
print("meow")
but that method has an issue. You have to put something in the except place so i found this:
但这种方法有问题。你必须在除了地方放一些东西,所以我发现了这个:
list = ["a", "b", "c"]
if "a" in str(list):
list.remove("a")

