微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

高效计算多个集合的异或/对称差集合列表

如何解决高效计算多个集合的异或/对称差集合列表

我有任意数量的 Python 集,例如

>>> a = {1,2,3}
>>> b = {3,4,5}
>>> c = {5,6,7}
>>> d = {7,8,1}

我想计算它们的“组合”对称差异,即我想对它们全部进行异或:

>>> a ^ b ^ c ^ d
{2,8}

在我的用例中,我实际上是在处理集合列表:

>>> l = [a,b,c,d]
>>> l
[{1,3},{3,5},{5,7},{1,7,8}]

目前,我正在遍历列表以实现我想要的:

>>> res = l[0].copy()
>>> for item in l[1:]:
...     res.symmetric_difference_update(item)
>>> res
{2,8}

我想知道是否有更有效的方法,最好不经过 Python for 循环。 Python 中的设置操作实际上非常快,但我的列表可能会变得很长,因此具有讽刺意味的是 for 循环本身成为一个瓶颈。


编辑 (1)

我假设列表中所有集合的每个可能条目在列表中的所有集合中出现的次数不超过两次。


编辑 (2)

一些基准:

from typing import List,Set
from functools import reduce
from collections import defaultdict

length = 1_000
data = [
    {idx - 1,idx,idx + 1}
    for idx in range(3_000,3_000 + length * 2,2)
]

def test_loop1(l: List[Set[int]]) -> Set[int]:
    res = l[0].copy()
    for item in l[1:]:
        res.symmetric_difference_update(item)
    assert len(res) == len(l) + 2
    return res

test_loop1:121 微秒 ± 321 纳秒

def test_loop2(l: List[Set[int]]) -> Set[int]:
    res = set()
    for item in l:
        res.symmetric_difference_update(item)
    assert len(res) == len(l) + 2
    return res

test_loop2:112 µs ± 3.16 µs

def test_reduce1(l: List[Set[int]]) -> Set[int]:
    res = reduce(Set.symmetric_difference,l)
    assert len(res) == len(l) + 2
    return res

test_reduce1:9.89 毫秒 ± 20.6 微秒

def test_dict1(l: List[Set[int]]) -> Set[int]:
    """
    A general solution allowing for entries to occur more than twice in the input data
    """
    d = defaultdict(int)
    for item in l:
        for entry in item:
            d[entry] += 1
    res = {entry for item in l for entry in item if d[entry] == 1}
    assert len(res) == len(l) + 2
    return res

test_dict1:695 µs ± 5.11 µs

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。