给定一个可变的set
个对象,
A = set(1,2,3,4,5,6)
我可以构建一个 new 集,其中只包含那些不满足谓词的对象......
B = set(x for x in A if not (x % 2 == 0))
...但我如何修改A
到位以仅包含这些对象?如果可能的话,在线性时间内完成此操作,不构造O(n)大小的临时对象,也不会从A
中删除任何内容,即使是暂时的,也不会满足谓词。
(此处使用的整数仅用于简化示例。在实际代码中,它们是Future
个对象,而我试图提取已经完成的那些,预计这只是一小部分总数。)
请注意,通常,Python中的安全性不会改变您正在迭代的对象。我不确定套装的准确规则(文件没有任何保证)。
我只需需要 3.4+的答案,但会得到更多的一般答案。
答案 0 :(得分:4)
(由于实施细节,实际上并不是O(1),但我不愿意删除它,因为它很干净。)
使用symmetric_difference_update
。
>>> A = {1,2,3,4,5,6}
>>> A.symmetric_difference_update(x for x in A if not (x % 2))
>>> A
{1, 3, 5}
答案 1 :(得分:2)
时间复杂度很高(二次方),但在O(1)空间中:
>>> A = {1,2,3,4,5,6}
>>> while modified:
... modified = False
... for x in A:
... if not x%2:
... A.remove(x)
... modified = True
... break
...
>>> A
{1, 3, 5}
答案 2 :(得分:2)
在您展示的非常具体的用例中,有一种方法可以在O(1)
空间中执行此操作,但它并不能很好地概括包含除int
个对象之外的任何内容的集合:
A = {1, 2, 3, 4, 5, 6}
for i in range(min(A), max(A) + 1):
if i % 2 != 0:
A.discard(i)
它还浪费时间,因为它会检查在集合中甚至不是的数字。对于除int
个对象以外的任何其他内容,我还无法想到一种方法,无需创建某种中间set
或某种容器。
对于更通用的解决方案,最好只使用谓词初始构建set
(如果您不需要首先使用set
进行其他操作)。像这样:
def items():
# maybe this is a file or a stream or something,
# where ever your initial values are coming from.
for thing in source:
yield thing
def predicate(item):
return bool(item)
A = set(item for item in items() if predicate(item))
答案 3 :(得分:0)
为了保持使用内存不变,这是唯一让我想到的东西
def filter_Set(predicate,origen:set) -> set:
resul = set()
while origen:
elem = origen.pop()
if predicate( elem ):
resul.add( elem )
return resul
def filter_Set_inplace(predicate,origen:set):
resul = set()
while origen:
elem = origen.pop()
if predicate( elem ):
resul.add( elem )
while resul:
origen.add(resul.pop())
使用这个函数我将elems从一个集合移动到另一个集合,只保留那些满足谓词的那些