有没有一种巧妙的方法来获得一组差异的“剩余”?

2024-06-25 23:08:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我遇到了这个问题:

给定一个可数i,两个不相交的集合ab(其中通常ab包含的元素远远多于i)从a中删除在i中找到的所有元素,并将a中不被^}共享的所有元素添加到b

例如:

i = [0, 3]
a = {1, 2, 3, 4}
b = {5, 6, 7, 8}

应该导致

a = {1, 2, 4}
b = {0, 5, 6, 7, 8}

Venn diagram of the example

根据该图,灰色子集应为空。操作完成后,我希望浅蓝色子集连接到b,黄色重叠从a中删除

为了解决这个问题,我编写了以下Python函数:

def foo(i, a, b):
    set_i = set(i)
    b |= set_i - a
    a -= set_i

这是可行的,但它不是很漂亮,仍然会做两次事情(不同的是aset_i

哪种方式更有效


Tags: 函数元素foodef方式事情子集set
2条回答

你就不能像你描述的那样直接做吗:

def foo(i, a, b):

    for el in i:
        if el in a:
            a.remove(el)
        else:
            b.add(el)

我不会在适当的地方对a和b进行变异,特别是因为它们是作为函数的参数提供的,所以安全的版本应该是

def foo(i, a, b):

    a_new = a.copy()
    b_new = b.copy()

    for el in i:
        if el in a:
            a_new.remove(el)
        else:
            b_new.add(el)

    return a_new, b_new

在一般情况下,它会更有效,因为i是一个iterable(可能是一个实际的迭代器),您只需对它迭代一次。如果您将它转换为一个集合,那么在内部它将被迭代一次,然后对于每个集合操作,至少重复两次

您还可以像这样使用来自itertoolsgroupby

from itertools import groupby

def foo(i, a, b):

    for in_a, i_group in groupby(i, key=lambda x: x in a):
    
        if in_a:
            a -= set(i_group)
        else:
            b |= set(i_group)

尝试:

def foo(i, a, b):
    a -= set(i)
    b |= a

相关问题 更多 >