Python 有没有一条捷径可以到达;“剩余”;有什么区别?
我遇到了这个问题: 给定一个可数Python 有没有一条捷径可以到达;“剩余”;有什么区别?,python,set,Python,Set,我遇到了这个问题: 给定一个可数i,两个不相交的集合a和b(其中通常a和b包含的元素远远多于i)从a中删除i中找到的所有元素,并将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} 根据该图,灰色子集应为空。操作完成后,我希望浅蓝色子集加入到b,黄色重叠部分从a中删除 为了解决这个问题,我编写了以下Python函数: def foo(
i
,两个不相交的集合a
和b
(其中通常a
和b
包含的元素远远多于i
)从a
中删除i
中找到的所有元素,并将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}
根据该图,灰色子集应为空。操作完成后,我希望浅蓝色子集加入到b
,黄色重叠部分从a
中删除
为了解决这个问题,我编写了以下Python函数:
def foo(i, a, b):
set_i = set(i)
b |= set_i - a
a -= set_i
这是可行的,但它不是很漂亮,仍然可以做两次事情(a和set_i的区别)
什么方法更有效?试试:
def foo(i,a,b):
a-=集合(i)
b |=a
难道你不能像你描述的那样简单地完成它吗:
def foo(i,a,b):
对于el in i:
如果el在a中:
a、 移除(el)
其他:
b、 加(el)
我不会在适当的地方对a和b进行变异,特别是因为它们是作为函数的参数提供的,所以安全的版本应该是
def foo(i,a,b):
a_new=a.copy()
b_new=b.copy()
对于el in i:
如果el在a中:
a_新。移除(el)
其他:
b_新添加(el)
返回a_new,b_new
在一般情况下,它会更有效,因为i
是一个iterable(可能是一个实际的迭代器),您只需对它迭代一次。如果您将它转换为一个集合,那么在内部它将被迭代一次,然后对于每个集合操作,至少重复两次
您还可以使用itertools
中的groupby
,如下所示:
从itertools导入groupby
def foo(i、a、b):
对于in_a,i_group in groupby(i,key=lambda x:x in a):
如果在a中:
a-=集合(i_组)
其他:
b |=集合(i|u群)
这根本不是等价的,它可以将i的元素移动到a和b,但也可以将以前在a中的所有元素移动到b中。你能给我们一些输入和预期输出的例子吗?我看不出差异被计算了两次:i-a
不是a-i
的简单补充。对不起,我想我不明白“不容易补足”这一部分。这两条线的差异是如何计算出来的?我建议你做一个维恩图,三个重叠的圆圈,勾勒出你想要的结果。我想,b的所有元素都应该保留,即使它们在b和a的交叉点。这让我意识到我忘了指定a和b应该是不相交的。我可以这样做,但我假设只迭代一次并不能弥补从a中删除并添加到b的额外工作,而不是通过集合操作。我也承认改变输入参数不是一种很好的风格,但这正是我想要做的,在每次调用中复制它们的内容并不能解决这个问题。groupby与我想象的很接近,但在我看来,调用这个lambda只是额外的工作,而且该函数要求输入迭代器按键排序。添加到a和从b中删除看起来是额外的工作,但在内部,set operations逐项工作,因此只有您的代码看起来效率较低,但是实际执行的时间更快,你可以计时,看看什么更有效率。同意,看起来它们的工作原理是一样的。但是,现在我不确定是否显式检查“a中的el”是额外的工作,因为set.remove中可能已经有类似的内容了。因此,在python中,这可能无法以绝对的效率完成。@TheodorStraube我刚刚注意到我的第一个解决方案有一个bug-如果同一元素在I
和a
中多次出现,它的第一次出现将从a
中删除,但随后的元素将添加到b
,因为它将不再出现在a
中。使用groupby
的最后一个解决方案工作正常,因为在迭代组之前执行组生成。