[英]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()
方法(或类似方法)是有原因的吗?
其他答案是正确的; 如果您希望所有指向旧列表的名称都指向新列表,您可以使用切片分配。
然而,这并不是真正的就地创建; 新列表首先在别处创建。 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.