如何检查Python列表是否包含另一个列表的元素(不忽略重复项)

3
我正在尝试检查一个小列表中是否包含另一个更大列表中存在的所有数字。 情况1:- 列表1:[97,97,196],列表2:[97,97,101,103,196]
  • 这应该返回True,因为列表1中的所有元素已经在列表2中了
情况2:- 列表1:[97,97,196],列表2:[97,101,103,196]
  • 这应该返回False,因为列表1有两个97,而列表2只包含一个97
list1 = [97,97,196]
list2 = [97,97,99,101,103,196]


def isConsist(list1,list2):
    check = False

    # Iterate in the 1st list
    for m in list1:

        # Iterate in the 2nd list
        for n in list2:

            # if there is a match
            if m == n:
                check = True
                list2.remove(n) // remove the found element 
            else:
                check = False
                return False
    return check

check = isConsist(list1,list2)
print(check)


这是我的代码,但它没有正确工作。

我的代码得到了错误的结果,因为在检查第一个列表中的196时,它与第二个列表中的99进行比较,然后返回False。


在Python中查找列表中的子列表 [已关闭] - wim
4个回答

3
使用collections.Counter对象,它可以像multiset一样使用。本质上,您正在询问在将list1的multiset与list2的multiset取差集后,所得到的multiset是否为空。因此,请考虑以下内容:
>>> from collections import Counter
>>> list1 = [97,97,196]
>>> list2 = [97,97,101,103,196]
>>> Counter(list1) - Counter(list2)
Counter()

但是如果我们这样做:

>>> list2 = [97,101,103,196]
>>> Counter(list1) - Counter(list2)
Counter({97: 1})

注意,上述方法将是线性时间和空间。

另一种从高层次思考的方式:

  1. 使用字典计算list1中的对象数量,称之为counts1
  2. 使用字典计算list2中的对象数量,称之为counts2
  3. 从匹配键的count1中减去count2中的计数
  4. 如果所有计数都为0或负数,则结果为true,否则为false。

总而言之,您的函数可以写成:

from collections import Counter

def is_consistent(list1, list2):
    return bool(Counter(list1) - Counter(list2))

编辑:

刚刚发现,自 Python 3.10 起,collections.Counter 类现在支持多集合相等、子集和超集关系的丰富比较运算符!

因此,您实际上可以使用以下代码:

def is_consistent(list1, list2):
    return Counter(list1) <= Counter(list2)

请注意,如果仅出于阐明目的,您可以使用常规字典“手动”完成此操作。
def _count(lst):
    counts = {}
    for item in lst:
        counts[item] = counts.get(item, 0) + 1
    return counts

def is_consistent(list1, list2):
    counts1 = _count(list1)
    counts2 = _count(list2)
    for k in counts1:
        counts1[k] -= counts2.get(k, 0)
    for v in counts1.values():
        if v > 0:
            return False
    return True

现在,你的方法接近正确(尽管它是低效的,二次时间和线性空间),如果像你指出的那样,你不提前返回。这是我认为你试图达到的目标:

def is_consistent(list1, list2):
    list1_copy = list1.copy()
    for item in list2:
        if item in list1:
            try:
                list1_copy.remove(item)
            except ValueError:
                pass
    return bool(list1_copy)

请注意,bool(list1_copy) 等同于 len(list1_copy) == 0。这与编程有关。

2

将列表转换为集合并不能解决您的问题。最好的方法是使用collections.Counter。这是我的代码:

from collections import Counter

list1 = [97, 97, 196]
list2 = [97, 97, 99, 101, 103, 196]


def consist(a, b):
    a_count = Counter(a)
    b_count = Counter(b)
    for key in a_count:
        if key not in b_count:
            return False
        if b_count[key] > a_count[key] or a_count[key] > b_count[key]:
            return False
    return True


print(consist(list1, list2))

在第一个if语句中,我们检查list1中的元素是否存在于list2中。在第二个if语句中,我们检查list1中的元素数量是否与list2中的元素数量相同。这是我得到的最佳答案,希望对你有所帮助。 :)

if条件应为a_count > b_count。 - Mustafa Adel
@MustafaAdel 对的,这将是在第二个if条件中的附加条件。已更新答案。 - Nilesh Bhave

1

嘿!这是我的解决方案:

首先,让我们检查第一个列表是否是第二个列表的子列表,因为如果不是,继续进行就没有任何意义。

然后我只在第一个列表中迭代,并检查两个列表中是否恰好有n个该数字的出现次数。如果这是错误的,则返回False,否则如果一切正常,则返回True。

def isConsist(list1, list2):

# check if all the element in list1 are in list2
x = set(list1)
y = set(list2)
if not x.issubset(y):
    return False

# Iterate in the 1st list
for n1 in range(len(list1)):

    if list1.count(list1[n1]) != list2.count((list1[n1])):
        return False

return True

print(isConsist(list1, list2))


-1
你可以尝试类似这样的代码:
list1 = [97,97,196] 
list2 = [97,101,103,196]
[list1.remove(i) for i in list2 if i in list1]
print(bool(list1))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接