如何检查列表中的所有项目是否都在另一个列表中?

时间:2013-02-28 23:34:07

标签: python

我有两个名单

List1 = ['a','c','c']
List2 = ['x','b','a','x','c','y','c']

现在我想知道List2中是否存在List1的所有元素。在这种情况下,所有的都有。我不能使用子集函数,因为我可以在列表中重复元素。我可以使用for循环来计算List1中每个项目的出现次数,并查看它是否小于或等于List2中出现的次数。有更好的方法吗?

感谢。

6 个答案:

答案 0 :(得分:30)

当出现次数无关紧要时,您仍然可以通过动态创建一个集来使用子集功能:

>>> list1 = ['a', 'c', 'c']
>>> list2 = ['x', 'b', 'a', 'x', 'c', 'y', 'c']
>>> set(list1) < set(list2)
True

如果您需要检查每个元素在第二个列表中是否与第一个列表中显示的次数相同,您可以使用Counter类型并定义自己的子集关系:

>>> 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

答案 1 :(得分:3)

请注意以下事项:

>>>listA = ['a', 'a', 'b','b','b','c']
>>>listB = ['b', 'a','a','b','c','d']
>>>all(item in listB for item in listA)
True

如果您像英语一样阅读“全部”行,这没有错,但可能会产生误导,因为listA有第三个'b'但listB没有。

这也有同样的问题:

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

使用集合不是多次出现元素匹配的综合解决方案。

但是这里是一个单线解决方案/适应shantanoo的答案,没有尝试/除了:

all(True if sequenceA.count(item) <= sequenceB.count(item) else False for item in sequenceA)

使用三元条件运算符包装列表推导的内置函数。 Python太棒了!请注意,“&lt; =”不应为“==”。

使用此解决方案序列A和B可以是类型元组和列表以及具有“计数”方法的其他“序列”。两个序列中的元素可以是大多数类型。我不会像现在这样使用dicts,因此使用“sequence”而不是“iterable”。

答案 2 :(得分:0)

使用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

答案 3 :(得分:0)

  

我不能使用子集函数,因为我可以在列表中重复元素。

这意味着您希望将列表视为multisets而不是设置。在Python中处理多集的常用方法是使用collections.Counter

  

Counter是用于计算可哈希对象的dict子类。它是一个无序集合,其中元素存储为字典键,其计数存储为字典值。计数允许为任何整数值,包括零或负计数。 Counter类与其他语言的包或多重集相似。

而且,虽然可以通过循环和比较计数来实现多个集合的子集(通过Counter实现),但在poke's answer中,这是不必要的 - 就像您<通过循环和测试set,em>可以实现集合的子集(通过frozensetin实现),但这是不必要的。

Counter类型已经实现了以明显的方式为多集合扩展的所有集合运算符。&lt; 1 因此,您可以根据这些运算符编写子集,它将起作用开箱即用setCounter

具有(多)组差异: 2

def is_subset(c1, c2):
    return not c1 - c2

或使用(多)集交集:

def is_subset(c1, c2):
    def c1 & c2 == c1

<子> 1。您可能想知道为什么,如果Counter实现了集合运算符,它就不会为正确的子集和子集实现<<=。虽然我找不到电子邮件主题,但我很确定已经讨论了这个问题,答案是&#34;设置运营商&#34;被定义为在collections.abc.Set的初始版本中定义的特定运算符集合(已经扩展,IIRC ...),并非所有set为了方便而恰好包含的运算符,以完全相同的方式Counter intersection之类的&之类的其他类型对set以外的其他类型友好的方法bool

<子> 2。这取决于Python中的集合在空的时候是假的,否则就是假的。对于内置类型,这记录为herelen测试回溯到Counter的事实被解释为here - 但它最终只是一个约定,所以&#34;准收藏&#34;像numpy数组可以违反它,如果他们有充分的理由。它适用于真正的收藏品#34;例如OrderedDictlen(c1 - c2) == 0等。如果您真的担心这一点,可以写NumberFormatter,但请注意这违反了PEP 8的精神。

答案 4 :(得分:-1)

如果List1中的所有项目都在List2

中,则返回true
def list1InList2(list1, list2):
    for item in list1:
        if item not in list2:
            return False
    return True

答案 5 :(得分:-1)

def 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'