繁体   English   中英

如何通过就地过滤修改 python collections?

[英]How to modify python collections by filtering in-place?

我想知道,Python 是否有办法修改 collections 而无需创建新的。 例如:

lst = [1, 2, 3, 4, 5, 6]
new_lst = [i for i in lst if i > 3]

工作正常,但创建了一个新集合。 Python collections 缺少可以修改集合 object 的filter()方法(或类似方法)是有原因的吗?

如果您想就地执行此操作,只需使用

lst[:] = [i for i in lst if i > 3]

不会更快或节省任何内存,但它会更改对象,如果这是您需要的语义。

其他答案是正确的; 如果您希望所有指向旧列表的名称都指向新列表,您可以使用切片分配。

然而,这并不是真正的就地创建; 新列表首先在别处创建。 Sven 的回答中的链接很好。

原因,没有一个真正运行就地是,同时使一个新的名单一样,为O(n),每一个真正就地项目的搬迁将是O(K)本身,其中k是长度从删除点开始的列表。 使用 Python 列表避免这种情况的唯一方法是使用一些临时存储,这就是您使用切片分配所做的。

collections.deque上的就地 O(n) 过滤器的示例,以防您不需要将数据存储在list

from collections import deque

def dequefilter(deck, condition):
    for _ in xrange(len(deck)):
        item = deck.popleft()
        if condition(item):
            deck.append(item)

deck = deque((1, 2, 3, 4, 5))
dequefilter(deck, lambda x: x > 2) # or operator.gt(2)
print deck
# deque([3, 4, 5])

更正@larsmans 原始解决方案,您可以这样做

    i = 0
    while i < len(lst):
        if lst[i] <= 3:
            del lst[i]
        else:
            i += 1

或者

    i = len(lst)
    while i > 0:
        if lst[i-1] <= 3:
            del lst[i-1]
        i -= 1

原因是del发生的“索引偏移”。 如果我del某个索引,则需要重新检查该索引,因为它现在拥有不同的值。

也许我有点晚了,但是由于没有发布其他“O(n) 时间/O(1) 内存”解决方案,甚至有人声称这是不可能的,我认为我应该发布这个。

# Retains the elements of xs for which p returned true 
def retain(xs, p):
    w = 0
    for x in xs:
        if p(x):
            xs[w] = x
            w += 1
    del xs[w:]

@Sven Marnach 的lst[:]解决方案是一种选择。 您还可以使用恒定的额外内存就地执行此操作,使用

>>> i = 0
>>> while i < len(lst):
...  if lst[i] <= 3:
...   del lst[i]
...  else:
...   i += 1
... 
>>> lst
[4, 5, 6]

...但是这个解决方案不是很可读,并且由于涉及所有元素移位而需要二次时间。

因为不需要

lst[:] = [i for i in lst if i > 3]

我认为这是到位转型;

lst = [1,2,3,4,5,6,7,8,9,10,11]
to_exclude = [8,4,11,9]
print 'lst == %s\nto_exclude == %s' % (lst,to_exclude)

for i in xrange(len(lst)-1,-1,-1):
    if lst[i] in to_exclude:
        lst.pop(i)

print '\nlst ==',lst

结果

lst == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
to_exclude == [8, 4, 11, 9]

lst == [1, 2, 3, 5, 6, 7, 10]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM