从集合中删除满足谓词的所有元素

时间:2015-12-09 19:46:33

标签: python python-3.x

给定一个可变的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+的答案,但会得到更多的一般答案。

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从一个集合移动到另一个集合,只保留那些满足谓词的那些