Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中不使用特定元素快速返回列表的方法_Python - Fatal编程技术网

在Python中不使用特定元素快速返回列表的方法

在Python中不使用特定元素快速返回列表的方法,python,Python,如果我有一张按任意顺序排列的卡片套装列表,如下所示: suits = ["h", "c", "d", "s"] 我想返回一个不带'c' noclubs = ["h", "d", "s"] 有没有一个简单的方法可以做到这一点 suits = ["h","c", "d", "s"] noclubs = [x for x in suits if x != "c"] 如果您不需要单独的noclubs >>> suits = ["h","c", "d", "s"] >>

如果我有一张按任意顺序排列的卡片套装列表,如下所示:

suits = ["h", "c", "d", "s"]
我想返回一个不带
'c'

noclubs = ["h", "d", "s"]
有没有一个简单的方法可以做到这一点

suits = ["h","c", "d", "s"]

noclubs = [x for x in suits if x != "c"]
如果您不需要单独的
noclubs

>>> suits = ["h","c", "d", "s"]
>>> suits.remove("c")

如果您希望删除特定元素(而不仅仅是筛选)很重要,那么您需要接近以下内容:

noclubs = [x for i, x in enumerate(suits) if i != suits.index('c')]

你也可以考虑使用<代码> set >代码>如果你的问题与扑克牌有关,那么语义上是正确的。

如果顺序不重要,可以使用一个集合操作:

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']
您可以使用过滤器(或itertools中的ifilter)

您还可以使用列表构造进行筛选

suits = ["h","c", "d", "s"]
noclubs = [ i for i in suits if i!='c' ]

这个问题已经得到了回答,但我想指出的是,使用列表理解要比使用
.remove()
慢得多

我的机器上的一些配置文件(使用Python 3.6.9)

如果您使用最快的方式复制列表(可读性不强),您将比使用列表理解快约45%。但是,如果您使用
list()
类复制列表(这是一个更常见的Pythonic类),那么您将比使用列表理解慢25%

真的,一切都很快。我认为可以提出这样的论点:
.remove()
比列表理解技术更具可读性,但它不一定更快,除非您有兴趣放弃复制中的可读性


在这种情况下,列表理解的最大优点是它更简洁(即,如果您有一个函数,出于某种原因从给定列表中删除一个元素,它可以在一行中完成,而另一个方法需要3行)。有时一行代码非常方便(尽管它们通常以一些可读性为代价)。此外,如果您不知道要删除的元素是否确实在列表中,则使用列表理解会更好。While
.remove()
将抛出一个
值错误
,列表理解将按预期操作。

不使用for循环或lambda函数并保留顺序:

suits = ["h","c", "d", "s"]
noclubs = suits[:suits.index("c")]+suits[suits.index("c")+1:]

我知道它在内部仍然会使用循环,但至少您不必在外部使用它们。

不幸的是,在默认情况下,Python中似乎没有类似的东西

有几个答案,但我认为我应该使用迭代器添加一个。如果可以接受就地更改,这将是最快的。如果您不想更改原始设置,只想循环一个过滤集,这应该是非常快的:

实施:

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
用法:

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]
li=列表(范围(5))
没有(李,3)
# 
列表(没有(li,(0,2)))
# [1, 3, 4]
清单(无(李,3))
# [0, 1, 2, 4]
因此,它是一个生成器-您需要调用
list
或其他东西使其永久化


如果您只想删除一个索引,当然可以使用
k==remove\u index
而不是一个集合来加快删除速度。

一种可能是使用:

除了
部分
之外,还可以在此处使用
'c'
方法:

>>> list(filter('c'.__ne__, suits))
['h', 'd', 's']
然而,后一种方法被认为不是非常pythonic(通常不应该直接使用特殊的方法,从双下划线开始),如果列表包含混合类型,它可能会给出奇怪的结果,但它可能比
部分
方法快一点

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使用IPythons magic
%timeit
命令进行了测试。

我不能撒谎……我希望会有没有循环的东西。这在像R这样的语言中要短得多,更直观。我会避免使用这种解决方案,因为在我看来它是非常不优化的。使用.remove()IMHO快多了。@VisgeanSkeloru我不同意
.remove()
快多了。我在下面发布了一个答案来解决这个问题(很难在评论框中格式化代码).是的,你是对的,我的错误,我没有考虑复制列表所需的时间…我只是想从列表中删除一个元素,而不是创建新的列表…我还玩了复制模块,似乎[:]是复制的最快方法…循环总是以某种形式使用,例如,
remove
使用循环,尽管在
c
级别。有没有方法在不更改原始列表的情况下执行此操作?@AsheKetchum不幸的是,您最终必须复制列表。请注意,此答案仅计算第一次出现的循环的索引<代码>'c'
并对原始列表中的每个元素执行该操作。因此,如果原始列表中包含多个要删除的元素,则该函数将不起作用。即使它只包含一个元素,也会很慢。如果x!='c',最好只比较值。@MSeifert,我相信这是我回答的重点,创建一个ne删除特定元素的w列表,而不是筛选与某个谓词匹配的所有内容。我同意这可能更有效。此外,请注意,列表理解解决方案将在删除()时删除所有“c”字符将仅删除第一个。这是一个很好的方法,但速度不如使用
suits[:]
复制数组,然后使用
.remove()
删除元素。这里需要注意的是,仅从列表中删除值等于x的第一项。如果没有该项,则会引发
ValueError
。删除x的所有实例,如果该值不存在,则不会引发错误。
noclubs=filter(lambda i:i!='c',filter)
向我返回一个筛选器对象,而不是列表,它需要强制转换为列表是的,在python3中必须将其强制转换为列表,在python2中它直接作为列表返回。问题来自2013年。
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]
>>> 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']
>>> list(filter('c'.__ne__, suits))
['h', 'd', 's']
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)