找到多个集合的交集的最佳方法?

发布于 2024-08-27 09:16:24 字数 190 浏览 5 评论 0原文

我有一个集合列表:

setlist = [s1,s2,s3...]

我想要 s1 ∩ s2 ∩ s3 ...

我可以编写一个函数来通过执行一系列成对的 s1.intersection(s2) 等来完成此操作

。推荐的、更好的还是内置的方式?

I have a list of sets:

setlist = [s1,s2,s3...]

I want s1 ∩ s2 ∩ s3 ...

I can write a function to do it by performing a series of pairwise s1.intersection(s2), etc.

Is there a recommended, better, or built-in way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

月下凄凉 2024-09-03 09:16:24

从 Python 2.6 版开始,您可以对 set.intersection() 使用多个参数,就像

u = set.intersection(s1, s2, s3)

如果集合在列表中,这将转换为:

u = set.intersection(*setlist)

其中 *a_list列表扩展

请注意,set.intersection 不是静态的方法,但这使用函数符号来应用第一个集合与列表其余部分的交集。因此,如果参数列表为空,则会失败。

From Python version 2.6 on you can use multiple arguments to set.intersection(), like

u = set.intersection(s1, s2, s3)

If the sets are in a list, this translates to:

u = set.intersection(*setlist)

where *a_list is list expansion

Note that set.intersection is not a static method, but this uses the functional notation to apply intersection of the first set with the rest of the list. So if the argument list is empty this will fail.

不离久伴 2024-09-03 09:16:24

从 2.6 开始,set.intersection 接受任意多个可迭代对象。

>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s3 = set([2, 4, 6])
>>> s1 & s2 & s3
set([2])
>>> s1.intersection(s2, s3)
set([2])
>>> sets = [s1, s2, s3]
>>> set.intersection(*sets)
set([2])

As of 2.6, set.intersection takes arbitrarily many iterables.

>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s3 = set([2, 4, 6])
>>> s1 & s2 & s3
set([2])
>>> s1.intersection(s2, s3)
set([2])
>>> sets = [s1, s2, s3]
>>> set.intersection(*sets)
set([2])
坐在坟头思考人生 2024-09-03 09:16:24

显然 set.intersection 是您想要的,但如果您需要“取所有这些的总和”、“取所有这些的乘积”、“取所有的异或”的概括这些”,您正在寻找的是 reduce 函数:

from operator import and_
from functools import reduce
print(reduce(and_, [{1,2,3},{2,3,4},{3,4,5}])) # = {3}

print(reduce((lambda x,y: x&y), [{1,2,3},{2,3,4},{3,4,5}])) # = {3}

Clearly set.intersection is what you want here, but in case you ever need a generalisation of "take the sum of all these", "take the product of all these", "take the xor of all these", what you are looking for is the reduce function:

from operator import and_
from functools import reduce
print(reduce(and_, [{1,2,3},{2,3,4},{3,4,5}])) # = {3}

or

print(reduce((lambda x,y: x&y), [{1,2,3},{2,3,4},{3,4,5}])) # = {3}
九厘米的零° 2024-09-03 09:16:24

如果你没有Python 2.6或更高版本,另一种方法是编写一个显式的for循环:

def set_list_intersection(set_list):
  if not set_list:
    return set()
  result = set_list[0]
  for s in set_list[1:]:
    result &= s
  return result

set_list = [set([1, 2]), set([1, 3]), set([1, 4])]
print set_list_intersection(set_list)
# Output: set([1])

你也可以使用reduce

set_list = [set([1, 2]), set([1, 3]), set([1, 4])]
print reduce(lambda s1, s2: s1 & s2, set_list)
# Output: set([1])

但是,许多Python程序员不喜欢它,包括 Guido 本人

大约 12 年前,Python 获得了 lambda、reduce()、filter() 和 map(),(我相信)一位 Lisp 黑客错过了它们并提交了工作补丁。但是,尽管有 PR 价值,我认为这些功能应该从 Python 3000 中删除。

所以现在减少()。这实际上是我一直最讨厌的,因为除了一些涉及 + 或 * 的例子之外,几乎每次我看到带有非平凡函数参数的 reduce() 调用时,我都需要拿起笔和纸来在我理解 reduce() 应该做什么之前,先画出实际输入到该函数中的内容。因此,在我看来,reduce() 的适用性几乎仅限于关联运算符,在所有其他情况下,最好明确地写出累积循环。

If you don't have Python 2.6 or higher, the alternative is to write an explicit for loop:

def set_list_intersection(set_list):
  if not set_list:
    return set()
  result = set_list[0]
  for s in set_list[1:]:
    result &= s
  return result

set_list = [set([1, 2]), set([1, 3]), set([1, 4])]
print set_list_intersection(set_list)
# Output: set([1])

You can also use reduce:

set_list = [set([1, 2]), set([1, 3]), set([1, 4])]
print reduce(lambda s1, s2: s1 & s2, set_list)
# Output: set([1])

However, many Python programmers dislike it, including Guido himself:

About 12 years ago, Python aquired lambda, reduce(), filter() and map(), courtesy of (I believe) a Lisp hacker who missed them and submitted working patches. But, despite of the PR value, I think these features should be cut from Python 3000.

So now reduce(). This is actually the one I've always hated most, because, apart from a few examples involving + or *, almost every time I see a reduce() call with a non-trivial function argument, I need to grab pen and paper to diagram what's actually being fed into that function before I understand what the reduce() is supposed to do. So in my mind, the applicability of reduce() is pretty much limited to associative operators, and in all other cases it's better to write out the accumulation loop explicitly.

沧桑㈠ 2024-09-03 09:16:24

我相信最简单的做法是:

#assuming three sets
set1 = {1,2,3,4,5}
set2 = {2,3,8,9}
set3 = {2,10,11,12}

#intersection
set4 = set1 & set2 & set3

set4 将是 set1 、 set2 、 set3 的交集,并且包含值 2。

print(set4)

set([2])

I believe the simplest thing to do is:

#assuming three sets
set1 = {1,2,3,4,5}
set2 = {2,3,8,9}
set3 = {2,10,11,12}

#intersection
set4 = set1 & set2 & set3

set4 will be the intersection of set1 , set2, set3 and will contain the value 2.

print(set4)

set([2])
小红帽 2024-09-03 09:16:24

在这里,我为多个集合交集提供了一个通用函数,试图利用可用的最佳方法:

def multiple_set_intersection(*sets):
    """Return multiple set intersection."""
    try:
        return set.intersection(*sets)
    except TypeError: # this is Python < 2.6 or no arguments
        pass

    try: a_set= sets[0]
    except IndexError: # no arguments
        return set() # return empty set

    return reduce(a_set.intersection, sets[1:])

Guido 可能不喜欢 reduce,但我有点喜欢它:)

Here I'm offering a generic function for multiple set intersection trying to take advantage of the best method available:

def multiple_set_intersection(*sets):
    """Return multiple set intersection."""
    try:
        return set.intersection(*sets)
    except TypeError: # this is Python < 2.6 or no arguments
        pass

    try: a_set= sets[0]
    except IndexError: # no arguments
        return set() # return empty set

    return reduce(a_set.intersection, sets[1:])

Guido might dislike reduce, but I'm kind of fond of it :)

歌入人心 2024-09-03 09:16:24

Jean-François Fabre set.intesection(*list_of_sets) 答案绝对是最 Pyhtonic 的,并且是正确接受的答案。

对于那些想要使用reduce的人,以下方法也适用:

reduce(set.intersection, list_of_sets)

Jean-François Fabre set.intesection(*list_of_sets) answer is definetly the most Pyhtonic and is rightly the accepted answer.

For those that want to use reduce, the following will also work:

reduce(set.intersection, list_of_sets)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文