Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.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_Python 3.x - Fatal编程技术网

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

Python 从集合中删除满足谓词的所有元素,python,python-3.x,Python,Python 3.x,给定一组可变的对象 A = set(1,2,3,4,5,6) 我可以构造一个只包含那些不满足谓词的对象的新集合 B = set(x for x in A if not (x % 2 == 0)) 。。。但是如何修改A以只包含这些对象?如果可能,在线性时间内执行此操作,而不构造O(n)大小的临时对象,也不从A中删除任何不满足谓词的内容,即使是暂时的 (这里使用整数只是为了简化示例。在实际代码中,它们是Future对象,我试图提取那些已经完成的对象,预计它们只占总数的一小部分。) 请注意,一般来

给定一组可变的
对象

A = set(1,2,3,4,5,6)
我可以构造一个只包含那些不满足谓词的对象的新集合

B = set(x for x in A if not (x % 2 == 0))
。。。但是如何修改
A
以只包含这些对象?如果可能,在线性时间内执行此操作,而不构造O(n)大小的临时对象,也不从
A
中删除任何不满足谓词的内容,即使是暂时的

(这里使用整数只是为了简化示例。在实际代码中,它们是
Future
对象,我试图提取那些已经完成的对象,预计它们只占总数的一小部分。)

请注意,一般来说,在Python中,对正在迭代的对象进行变异并不安全。我不确定集合的精确规则(文档中没有任何保证)

我只需要一个3.4+的答案,但将采用更一般的答案。

(由于实现细节,实际上不是O(1),但我不愿意删除它,因为它非常干净。)

使用
symmetric\u difference\u 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}
(由于实现细节,实际上不是O(1),但我不愿意删除它,因为它非常干净。)

使用
symmetric\u difference\u 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}

具有可怕的时间复杂性(二次),但在O(1)空间中:


具有可怕的时间复杂性(二次),但在O(1)空间中:


在您展示的非常具体的用例中,有一种方法可以在
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
或某种容器的方法来实现这一点

对于更一般的解决方案,最好是使用谓词(如果您不需要先将
集合
用于任何其他内容)简单地首先构造
集合
。大概是这样的:

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))

在您展示的非常具体的用例中,有一种方法可以在
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
或某种容器的方法来实现这一点

对于更一般的解决方案,最好是使用谓词(如果您不需要先将
集合
用于任何其他内容)简单地首先构造
集合
。大概是这样的:

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))

为了保持记忆的使用不变,这是我唯一想到的事情

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())

通过这个函数,我将元素从一个集合移动到另一个集合,只保留那些满足谓词的元素,以保持内存的使用不变。这是我唯一想到的事情

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())

使用这个函数,我将元素从一个集合移动到另一个集合,只保留那些满足谓词的元素,而不是
O(1)
空间,因为它在内部将生成器转换为一个集合。我可能会使用显式的set参数和
difference\u update
。这也不是O(1)空间。如果将生成器转换为一个集合,而不是简单地迭代,我会感到惊讶。事实上,这不是O(1)空间,而是更明显的空间需求。也。如果没有,您将得到一个“在迭代过程中设置更改的大小”错误。我很惊讶它会这样做。它根本不改变那个集合,它只是在它上面迭代,所以似乎一开始就不需要创建集合。查看
set\u update\u internal
,在
symmetric\u difference\u update
中迭代生成器看起来并不比创建新的
set
对象慢。哦,好吧,它可能是O(1),但它不是。我猜它生成集合的原因是为了重复处理。它试图确保对称差分更新([1,1])
不会先取出1,然后再将其放回。但不是
O(1)
空间,因为它在内部将生成器转换为一个集合。我可能会使用显式的set参数和
difference\u update
。这也不是O(1)空间。如果将生成器转换为一个集合,而不是简单地迭代,我会感到惊讶。事实上,这不是O(1)空间,而是更明显的空间需求。也。如果没有,您将得到一个“在迭代过程中设置更改的大小”错误。我很惊讶它会这样做。它根本不改变那个集合,它只是在它上面迭代,所以似乎一开始就不需要创建集合。查看
set\u update\u internal
,在
symmetric\u difference\u update
中迭代生成器看起来并不比创建新的
set
对象慢。哦,好吧,它可能是O(1),但它不是。我猜它生成集合的原因是为了重复处理。它试图确保对称差分更新([1,1])不会将1取出然后再放回。O(1)空间在
O(len(A))
时间内不可能不直接拧紧内部构件。最大的潜在原因是,无法保证当您删除某些内容时哈希表不会收缩。(CPython恰好不会在删除时收缩表,但其他实现可能会有不同的行为。)我想说,如果唯一需要的空间是调整
A
,那么它可以在摊销的O(1)空间中完成,因为调整大小操作的数量将受到集合原始大小的限制。为了清楚起见,我的意思是我宁愿避免在我的代码中构造一个O(n)空间的scratch对象;如果口译员决定