4

我知道我可以测试 set1 是否是 set2 的子集:

{'a','b','c'} <= {'a','b','c','d','e'} # True

但以下也是正确的:

{'a','a','b','c'} <= {'a','b','c','d','e'} # True

我如何让它考虑集合中的元素出现的次数,以便:

{'a','b','c'}     <= {'a','b','c','d','e'}      # True
{'a','a','b','c'} <= {'a','b','c','d','e'}      # False since 'a' is in set1 twice but set2 only once
{'a','a','b','c'} <= {'a','a','b','c','d','e'}  # True because both sets have two 'a' elements

我知道我可以做类似的事情:

A, B, C = ['a','a','b','c'], ['a','b','c','d','e'], ['a','a','b','c','d','e']
all([A.count(i) == B.count(i) for i in A]) # False
all([A.count(i) == C.count(i) for i in A]) # True

但我想知道是否有更简洁的东西set(A).issubset(B,count=True)或一种远离列表推导的方法。谢谢!

4

5 回答 5

10

如评论中所述,可能的解决方案是Counter

from collections import Counter

def issubset(X, Y):
    return len(Counter(X)-Counter(Y)) == 0
于 2013-03-04T18:49:07.093 回答
3

对您的问题的简短回答是没有集合操作可以做到这一点,因为集合的定义不提供这些操作。IE 定义您正在寻找的功能将使数据类型不是一个集合。

根据定义,集合具有唯一的、无序的成员:

>>> print {'a', 'a', 'b', 'c'}
set(['a', 'c', 'b'])
>>> {'a', 'a', 'b', 'c'} == {'a', 'b', 'c'}
True
于 2013-03-04T18:39:31.993 回答
1

结合以前的答案给出了一个尽可能干净和快速的解决方案:

def issubset(X, Y):
    return all(v <= Y[k] for k, v in X.items())
  • 在@A.Rodas 版本中没有创建实例而不是 3(两个参数必须已经是 Counter 类型,因为这是处理多重集的 Pythonic 方式)。
  • 一旦谓词被伪造,就提前返回(短路)。
于 2017-06-20T19:52:22.250 回答
0

由于@DSM 删除了他的解决方案,我将借此机会提供一个原型,您可以在此基础上进行扩展

>>> class Multi_set(Counter):
    def __le__(self, rhs):
        return all(v == rhs[k] for k,v in self.items())


>>> Multi_set(['a','b','c']) <= Multi_set(['a','b','c','d','e'])
True
>>> Multi_set(['a','a','b','c']) <= Multi_set(['a','b','c','d','e'])
False
>>> Multi_set(['a','a','b','c']) <= Multi_set(['a','a','b','c','d','e'])
True
>>> 
于 2013-03-04T18:46:36.947 回答
0

对于那些对多集包含的通常概念感兴趣的人,测试多集包含的最简单方法是使用多集的交集:

from collections import Counter

def issubset(X, Y):
    return X & Y == X

issubset(Counter("ab"), Counter("aab"))  # returns True
issubset(Counter("abc"), Counter("aab")) # returns False

这是幂等半环中使用的标准思想。

于 2019-08-22T11:37:49.100 回答