在 Python 中返回没有特定元素的列表的快速方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15738700/
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
A quick way to return list without a specific element in Python
提问by fox
If I have a list of card suits in arbitrary order like so:
如果我有一个任意顺序的卡片套装列表,如下所示:
suits = ["h", "c", "d", "s"]
and I want to return a list without the 'c'
我想返回一个没有 'c'
noclubs = ["h", "d", "s"]
is there a simple way to do this?
有没有一种简单的方法可以做到这一点?
采纳答案by jamylak
>>> suits = ["h","c", "d", "s"]
>>> noclubs = list(suits)
>>> noclubs.remove("c")
>>> noclubs
['h', 'd', 's']
If you don't need a seperate noclubs
如果你不需要单独 noclubs
>>> suits = ["h","c", "d", "s"]
>>> suits.remove("c")
回答by avasal
suits = ["h","c", "d", "s"]
noclubs = [x for x in suits if x != "c"]
回答by Ceasar Bautista
If it is important that you want to remove a specificelement (as opposed to just filtering), you'll want something close to the following:
如果您想删除特定元素(而不是仅仅过滤)很重要,那么您需要接近以下内容:
noclubs = [x for i, x in enumerate(suits) if i != suits.index('c')]
You may also consider using a sethere to be more semantically correct if indeed your problem is related to playing cards.
set如果您的问题确实与扑克牌有关,您也可以考虑使用here 在语义上更正确。
回答by Ceasar Bautista
If order doesn'tmatter, a set operation can be used:
如果为了不打紧,一组操作可用于:
suits = ["h", "c", "d", "s"]
noclubs = list(set(suits) - set(["c"]))
# note no order guarantee, the following is the result here:
# noclubs -> ['h', 's', 'd']
回答by Muayyad Alsadi
you can use filter (or ifilter from itertools)
您可以使用过滤器(或来自 itertools 的 ifilter)
suits = ["h","c", "d", "s"]
noclubs = filter(lambda i: i!='c', suits)
you can also filter using list construct
您还可以使用列表构造进行过滤
suits = ["h","c", "d", "s"]
noclubs = [ i for i in suits if i!='c' ]
回答by alukach
This question has been answered but I wanted to address the comment that using list comprehension is much slower than using .remove().
这个问题已得到解答,但我想解决使用列表理解比使用.remove().
Some profiles from my machine (notebookusing Python 3.6.9).
我机器上的一些配置文件(使用 Python 3.6.9 的笔记本)。
x = ['a', 'b', 'c', 'd']
%%timeit
y = x[:] # fastest way to copy
y.remove('c')
1000000 loops, best of 3: 203 ns per loop
%%timeit
y = list(x) # not as fast copy
y.remove('c')
1000000 loops, best of 3: 274 ns per loop
%%timeit
y = [n for n in x if n != 'c'] # list comprehension
1000000 loops, best of 3: 362 ns per loop
%%timeit
i = x.index('c')
y = x[:i] + x[i + 1:]
1000000 loops, best of 3: 375 ns per loop
If you use the fastest way to copy a list (which isn't very readable), you will be about 45% faster than using list comprehension. But if you copy the list by using the list()class (which is much more common and Pythonic), then you're going to be 25% slower than using list comprehension.
如果你使用最快的方式来复制一个列表(它不是很易读),你会比使用列表理解快 45%。但是,如果您使用list()类(更常见且 Python 风格)复制列表,那么您将比使用列表理解慢 25%。
Really, it's all pretty fast. I think the argument could be made that .remove()is more readable than list a list comprehension technique, but it's not necessarily faster unless you're interested in giving up readability in the duplication.
真的,这一切都非常快。我认为可以提出.remove()比列出列表理解技术更具可读性的论点,但它不一定更快,除非您有兴趣放弃重复的可读性。
The big advantage of list comprehension in this scenario is that it's much more succinct (i.e. if you had a function that was to remove an element from a given list for some reason, it could be done in 1 line, whilst the other method would require 3 lines.) There are times in which one-liners can be very handy (although they typically come at the cost of some readability). Additionally, using list comprehension excels in the case when you don't actually know if the element to be removed is actually in the list to begin with. While .remove()will throw a ValueError, list comprehension will operate as expected.
在这种情况下列表理解的最大优点是它更加简洁(即,如果您有一个函数要出于某种原因从给定列表中删除元素,则可以在 1 行中完成,而另一种方法则需要3 行。)有时单行代码非常方便(尽管它们通常以牺牲一些可读性为代价)。此外,在您实际上不知道要删除的元素是否确实在开始的列表中的情况下,使用列表推导式会更胜一筹。虽然.remove()会抛出ValueError,但列表理解将按预期运行。
回答by ierdna
Without using for loops or lambda functions and preserving order:
不使用 for 循环或 lambda 函数并保留顺序:
suits = ["h","c", "d", "s"]
noclubs = suits[:suits.index("c")]+suits[suits.index("c")+1:]
I'm aware that internally it'll still use loops, but at least you don't have to use them externally.
我知道在内部它仍然会使用循环,但至少你不必在外部使用它们。
回答by Mark
There doesn't seem to be anything like this built into Python by default unfortunately.
不幸的是,默认情况下,Python 中似乎没有类似的东西。
There are several answers but I though I'd add one using iterators. If changing in place is acceptable, that's going to be fastest. If you don't want to change the original and just want to loop over a filtered set, this should be pretty fast:
有几个答案,但我想我会使用迭代器添加一个。如果就地更改是可以接受的,那将是最快的。如果您不想更改原始文件而只想遍历过滤后的集合,这应该很快:
Implementation:
执行:
def without(iterable, remove_indices):
"""
Returns an iterable for a collection or iterable, which returns all items except the specified indices.
"""
if not hasattr(remove_indices, '__iter__'):
remove_indices = {remove_indices}
else:
remove_indices = set(remove_indices)
for k, item in enumerate(iterable):
if k in remove_indices:
continue
yield item
Usage:
用法:
li = list(range(5))
without(li, 3)
# <generator object without at 0x7f6343b7c150>
list(without(li, (0, 2)))
# [1, 3, 4]
list(without(li, 3))
# [0, 1, 2, 4]
So it is a generator - you'll need to call listor something to make it permanent.
所以它是一个发电机 - 你需要打电话list或其他东西才能使它永久。
If you only ever want to remove a single index, you can of course make it even faster by using k == remove_indexinstead of a set.
如果您只想删除单个索引,当然可以通过使用k == remove_index而不是集合来使其更快。
回答by MSeifert
One possibility would be to use filter:
一种可能性是使用filter:
>>> import operator
>>> import functools
>>> suits = ["h", "c", "d", "s"]
>>> # Python 3.x
>>> list(filter(functools.partial(operator.ne, 'c'), suits))
['h', 'd', 's']
>>> # Python 2.x
>>> filter(functools.partial(operator.ne, 'c'), suits)
['h', 'd', 's']
Instead of the partialone could also use the __ne__method of 'c'here:
而不是partial一个也可以使用这里的__ne__方法'c':
>>> list(filter('c'.__ne__, suits))
['h', 'd', 's']
However, the latter approach is not considered very pythonic (normally you shouldn't use special methods - starting with double underscores - directly) and it couldgive weird results if the list contains mixed types but it could be a bit faster than the partialapproach.
然而,后一种方法不被认为是非常pythonic(通常你不应该使用特殊方法——从双下划线开始——直接),如果列表包含混合类型,它可能会给出奇怪的结果,但它可能比partial方法快一点。
suits = ["h", "c", "d", "s"]*200 # more elements for more stable timings
%timeit list(filter('c'.__ne__, suits))
# 164 μs ± 5.98 μs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit list(filter(functools.partial(operator.ne, 'c'), suits))
# 337 μs ± 13.3 μs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit list(filter(lambda x: x != 'c', suits))
# 410 μs ± 13.7 μs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit [x for x in suits if x != "c"]
181 μs ± 465 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Python 3.5.2 tested with IPythons magic %timeitcommand.
Python 3.5.2 使用 IPythons 魔法%timeit命令测试。

