我有两个列表,比如说
List1 = ['a','c','c']
List2 = ['x','b','a','x','c','y','c']
现在我想找出List1中的所有元素是否都存在于List2中。在这种情况下,它们确实都存在。我不能使用subset函数,因为列表中可能有重复的元素。我可以使用for循环来计算List1中每个项出现的次数,并查看它是否小于或等于List2中出现的次数。有更好的方法吗?
谢谢。
我有两个列表,比如说
List1 = ['a','c','c']
List2 = ['x','b','a','x','c','y','c']
>>> list1 = ['a', 'c', 'c']
>>> list2 = ['x', 'b', 'a', 'x', 'c', 'y', 'c']
>>> set(list1).issubset(list2)
True
>>> from collections import Counter
>>> def counterSubset(list1, list2):
c1, c2 = Counter(list1), Counter(list2)
for k, n in c1.items():
if n > c2[k]:
return False
return True
>>> counterSubset(list1, list2)
True
>>> counterSubset(list1 + ['a'], list2)
False
>>> counterSubset(list1 + ['z'], list2)
False
>>> all(n <= c2[k] for k, n in c1.items())
True
请注意以下内容:
>>>listA = ['a', 'a', 'b','b','b','c']
>>>listB = ['b', 'a','a','b','c','d']
>>>all(item in listB for item in listA)
True
def list1InList2(list1, list2):
for item in list1:
if item not in list2:
return False
return True
请注意,以下内容无法正常工作:
>>>tupA = (1,2,3,4,5,6,7,8,9)
>>>tupB = (1,2,3,4,5,6,6,7,8,9)
>>>set(tupA) < set(TupB)
False
>>>set(tupA).issubset(set(tupB))
True
all(True if sequenceA.count(item) <= sequenceB.count(item) else False for item in sequenceA)
使用 Counter 和内置的交集方法的解决方案(注意,-
是适当的多重集合差异,而不是元素逐个减法):
from collections import Counter
def is_subset(l1, l2):
c1, c2 = Counter(l1), Counter(l2)
return not c1 - c2
测试:
>>> List1 = ['a','c','c']
>>> List2 = ['x','b','a','x','c','y','c']
>>> is_subset(List1, List2)
True
collections.Counter
:
Counter
是用于计算可哈希对象的字典子类。它是一个无序集合,其中元素存储为字典键,它们的计数存储为字典值。计数允许是任何整数值,包括零或负计数。 Counter
类类似于其他语言中的袋或多重集合。
并且,虽然你可以通过循环和比较计数来实现多重集的子集(使用Counter
实现),就像poke's answer中所述,但这是不必要的 - 就像你可以通过循环和测试in
来实现集合的子集(使用set
或frozenset
实现),但也是不必要的。
Counter
类型已经以显然的方式扩展了所有集合运算符用于多重集。<1因此,您可以仅使用这些运算符编写子集代码,并且它将适用于set
和Counter
。def is_subset(c1, c2):
return not c1 - c2
def is_subset(c1, c2):
def c1 & c2 == c1
1. 如果 Counter
实现了集合操作符,那么为什么它不直接实现真子集和子集的 <
和 <=
呢?虽然我找不到邮件记录,但我很确定这个问题已经讨论过了,答案是“集合操作符”被定义为最初版本的 collections.abc.Set
中定义的特定一组运算符(自那以后已经扩展了,如果我没记错的话...),而不是所有 set
为方便起见包含的运算符,就像 Counter
没有像 intersection
这样的命名方法,友好地对待其他类型,而不仅仅是 &
,就像 set
一样。
2. 这取决于Python中集合为空时期望为falsey,反之为truthy的事实。这里记录了内置类型的情况,bool
测试回退到len
的事实在这里解释了——但这最终只是一种约定,因此像numpy数组这样的“准集合”可以违反它,如果它们有充分的理由。对于像Counter
、OrderedDict
等“真实集合”,它仍然适用。如果您真的担心这个问题,可以编写len(c1 - c2) == 0
,但请注意,这与PEP 8的精神不符。
如果List1中的所有项都在List2中,则返回true
def list1InList2(list1, list2):
for item in list1:
if item not in list2:
return False
return True
all(item in List2 for item in List1)
。 - David Caindef check_subset(list1, list2):
try:
[list2.remove(x) for x in list1]
return 'all elements in list1 are in list2'
except:
return 'some elements in list1 are not in list2'
['s','e','r','','','','y']
和['','','','y']
的情况下,它会失败吗? - SIslamnot c1 - c2
代替all(n <= c2[k] for k, n in c1.items())
。这种方式不太易读,但可能更快。 - Aran-FeyCounter
是多重集合,它就不难理解了。但我认为fferri的基于交集的答案更明显地表达了多重集合操作(我不确定为什么fferri复制了我的差异答案而不是他们自己更好的交集答案,来自重复的问题...但是在我的回答中,我给出了两个答案)。 - abarnert