如何验证一个列表是否是另一个列表的子集?

2025-02-10 08:57:00
admin
原创
52
摘要:问题描述:我需要验证一个列表是否是另一个列表的子集——我所寻求的只是布尔返回。在交集之后对较小的列表进行相等性测试是最快的方法吗?考虑到需要比较的数据集的数量,性能至关重要。根据讨论添加更多事实:对于许多测试来说,这两个列表是否都相同?答案是相同的,因为其中一个列表是静态查找表。它需要是一个列表吗?它不需要 ...

问题描述:

我需要验证一个列表是否是另一个列表的子集——我所寻求的只是布尔返回。

在交集之后对较小的列表进行相等性测试是最快的方法吗?考虑到需要比较的数据集的数量,性能至关重要。

根据讨论添加更多事实:

  1. 对于许多测试来说,这两个列表是否都相同?答案是相同的,因为其中一个列表是静态查找表。

  2. 它需要是一个列表吗?它不需要 - 静态查找表可以是任何性能最佳的东西。动态查找表是一个字典,我们从中提取要执行静态查找的键。

在这种情况下,最佳解决方案是什么?


解决方案 1:

>>> a = [1, 3, 5]
>>> b = [1, 3, 5, 8]
>>> c = [3, 5, 9]
>>> set(a) <= set(b)
True
>>> set(c) <= set(b)
False

>>> a = ['yes', 'no', 'hmm']
>>> b = ['yes', 'no', 'hmm', 'well']
>>> c = ['sorry', 'no', 'hmm']
>>> 
>>> set(a) <= set(b)
True
>>> set(c) <= set(b)
False

解决方案 2:

使用set.issubset

例子:

a = {1,2}
b = {1,2,3}
a.issubset(b) # True
a = {1,2,4}
b = {1,2,3}
a.issubset(b) # False

Python 为此提供的高性能函数是set.issubset。但它确实有一些限制,因此不清楚它是否是您问题的答案。

列表可能包含多个项目,并且具有特定顺序。集合则不然。此外,集合仅适用于可哈希对象。

您问的是子集还是子序列(这意味着您需要一个字符串搜索算法)?对于许多测试来说,这两个列表是否相同?列表中包含的数据类型是什么?就此而言,它是否需要是一个列表?

您的另一篇帖子将字典和列表相交,使类型更加清晰,并确实获得了使用字典键视图来实现其类似集合的功能的建议。在这种情况下,它之所以有效,是因为字典键的行为类似于集合(以至于在 Python 中有集合之前,我们使用字典)。人们想知道这个问题在三个小时内是如何变得不那么具体的。

解决方案 3:

one = [1, 2, 3]
two = [9, 8, 5, 3, 2, 1]

all(x in two for x in one)

说明:生成器通过循环列表来创建布尔值,one检查该项目是否在列表中two。 如果每个项目都是真值,则返回,否则all()返回。True`False`

还有一个优点是,all在第一次出现缺失元素时返回 False,而不是必须处理每个项目。

解决方案 4:

假设项目是可哈希的

>>> from collections import Counter
>>> not Counter([1, 2]) - Counter([1])
False
>>> not Counter([1, 2]) - Counter([1, 2])
True
>>> not Counter([1, 2, 2]) - Counter([1, 2])
False

如果您不关心重复的项目,例如,[1, 2, 2]然后[1, 2]只需使用:

>>> set([1, 2, 2]).issubset([1, 2])
True

在交集之后对较小的列表进行相等性测试是执行此操作的最快方法吗?

.issubset是最快的方法。测试前检查长度issubset不会提高速度,因为您仍然需要迭代和检查 O(N + M) 个项目。

解决方案 5:

另一个解决方案是使用intersection

one = [1, 2, 3]
two = [9, 8, 5, 3, 2, 1]

set(one).intersection(set(two)) == set(one)

集合的交集将包含set one

(或者)

one = [1, 2, 3]
two = [9, 8, 5, 3, 2, 1]

set(one) & (set(two)) == set(one)

解决方案 6:

集合论不适用于列表,因为重复会导致使用集合论得到错误的答案。

例如:

a = [1, 3, 3, 3, 5]
b = [1, 3, 3, 4, 5]
set(b) > set(a)

没有意义。是的,它给出了错误的答案,但这并不正确,因为集合论只是比较:1,3,5 与 1,3,4,5。您必须包含所有重复项。

相反,您必须计算每个项目的每次出现次数,并进行大于等于检查。这并不昂贵,因为它不使用 O(N^2) 运算,也不需要快速排序。

#!/usr/bin/env python

from collections import Counter

def containedInFirst(a, b):
  a_count = Counter(a)
  b_count = Counter(b)
  for key in b_count:
    if a_count.has_key(key) == False:
      return False
    if b_count[key] > a_count[key]:
      return False
  return True


a = [1, 3, 3, 3, 5]
b = [1, 3, 3, 4, 5]
print "b in a: ", containedInFirst(a, b)

a = [1, 3, 3, 3, 4, 4, 5]
b = [1, 3, 3, 4, 5]
print "b in a: ", containedInFirst(a, b)

然后运行这个你会得到:

$ python contained.py 
b in a:  False
b in a:  True

解决方案 7:

one = [1, 2, 3]
two = [9, 8, 5, 3, 2, 1]

set(x in two for x in one) == set([True])

如果 list1 在 list2 中:

  • (x in two for x in one)生成一个列表True

  • 当我们执行 a 时,set(x in two for x in one)只有一个元素(True)。

解决方案 8:

如果我迟到了,请原谅我。;)

要检查某个是否set A是的子集set BPythonA.issubset(B)A <= B。它只适用于set并且效果很好,内部实现的复杂性未知。参考:https://docs.python.org/2/library/sets.html#set-objects

我想出了一个算法来检查是否list A是的子集,list B并附有以下注释。

  • 为了降低查找子集的复杂性,我发现
    sort在比较元素以满足子集的条件之前,首先对两个列表进行适当的比较。

  • 当第二个列表的元素值大于第一个列表的元素值break时,它对我有帮助。loop`B[j]`A[i]

  • last_index_j用于从上次中断的地方
    loop重新开始。它有助于避免从 的开头开始比较(您可能猜到这是不必要的,因为后续 的 都从开始)。list B`list Blist Bindex 0`iterations

  • 复杂性在于O(n ln n)对两个列表进行排序以及O(n)检查子集

O(n ln n) + O(n ln n) + O(n) = O(n ln n)

  • 代码中有很多语句来查看每个部分print发生了什么。这些仅用于理解。iteration`loop`

检查一个列表是否是另一个列表的子集

is_subset = True;

A = [9, 3, 11, 1, 7, 2];
B = [11, 4, 6, 2, 15, 1, 9, 8, 5, 3];

print(A, B);

# skip checking if list A has elements more than list B
if len(A) > len(B):
    is_subset = False;
else:
    # complexity of sorting using quicksort or merge sort: O(n ln n)
    # use best sorting algorithm available to minimize complexity
    A.sort();
    B.sort();

    print(A, B);

    # complexity: O(n^2)
    # for a in A:
    #   if a not in B:
    #       is_subset = False;
    #       break;

    # complexity: O(n)
    is_found = False;
    last_index_j = 0;

    for i in range(len(A)):
        for j in range(last_index_j, len(B)):
            is_found = False;

            print("i=" + str(i) + ", j=" + str(j) + ", " + str(A[i]) + "==" + str(B[j]) + "?");

            if B[j] <= A[i]:
                if A[i] == B[j]:
                    is_found = True;
                last_index_j = j;
            else:
                is_found = False;
                break;

            if is_found:
                print("Found: " + str(A[i]));
                last_index_j = last_index_j + 1;
                break;
            else:
                print("Not found: " + str(A[i]));

        if is_found == False:
            is_subset = False;
            break;

print("subset") if is_subset else print("not subset");

输出

[9, 3, 11, 1, 7, 2] [11, 4, 6, 2, 15, 1, 9, 8, 5, 3]
[1, 2, 3, 7, 9, 11] [1, 2, 3, 4, 5, 6, 8, 9, 11, 15]
i=0, j=0, 1==1?
Found: 1
i=1, j=1, 2==1?
Not found: 2
i=1, j=2, 2==2?
Found: 2
i=2, j=3, 3==3?
Found: 3
i=3, j=4, 7==4?
Not found: 7
i=3, j=5, 7==5?
Not found: 7
i=3, j=6, 7==6?
Not found: 7
i=3, j=7, 7==8?
not subset

解决方案 9:

下面的代码检查给定的集合是否是另一个集合的“真子集”

 def is_proper_subset(set, superset):
     return all(x in superset for x in set) and len(set)<len(superset)

解决方案 10:

在 Python 3.5 中,您可以执行 a[*set()][index]来获取元素。与其他方法相比,它的解决方案要慢得多。

one = [1, 2, 3]
two = [9, 8, 5, 3, 2, 1]

result = set(x in two for x in one)

[*result][0] == True

或者只使用 len 和 set

len(set(a+b)) == len(set(a))

解决方案 11:

这就是我知道一个列表是否是另一个列表的子集的方法,就我而言,顺序对我很重要。

def is_subset(list_long,list_short):
    short_length = len(list_short)
    subset_list = []
    for i in range(len(list_long)-short_length+1):
        subset_list.append(list_long[i:i+short_length])
    if list_short in subset_list:
        return True
    else: return False

解决方案 12:

大多数解决方案都认为列表没有重复项。如果您的列表确实有重复项,您可以尝试以下方法:

def isSubList(subList,mlist):
    uniqueElements=set(subList)
    for e in uniqueElements:
        if subList.count(e) > mlist.count(e):
            return False     
    # It is sublist
    return True

它确保子列表永远不会具有与列表不同的元素或大量的共同元素。

lst=[1,2,2,3,4]
sl1=[2,2,3]
sl2=[2,2,2]
sl3=[2,5]

print(isSubList(sl1,lst)) # True
print(isSubList(sl2,lst)) # False
print(isSubList(sl3,lst)) # False

解决方案 13:

由于没有人考虑过比较两个字符串,所以这是我的建议。

当然,您可能想检查管道(“|”)是否不属于任何一个列表的一部分,并且可能自动选择另一个字符,但您明白了。

使用空字符串作为分隔符不是一个解决方案,因为数字可以有几位数字([12,3]!= [1,23])

def issublist(l1,l2):
    return '|'.join([str(i) for i in l1]) in '|'.join([str(i) for i in l2])

解决方案 14:

如果您询问一个列表是否“包含”在另一个列表中,那么:

>>>if listA in listB: return True

如果您询问 listA 中的每个元素是否在 listB 中具有相等数量的匹配元素,请尝试:

all(True if listA.count(item) <= listB.count(item) else False for item in listA)
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用