[英]How can I verify if one list is a subset of another?
我需要验证一个列表是否是另一个列表的子集 - 我只寻求布尔返回。
在交叉路口后测试较小列表上的相等性是最快的方法吗? 考虑到需要比较的数据集数量,性能至关重要。
根据讨论添加更多事实:
对于许多测试,这两个列表中的任何一个是否相同? 其中之一是静态查找表。
必须是清单吗? 它不是 - 静态查找表可以是任何性能最好的东西。 动态的是一个字典,我们从中提取键来执行静态查找。
给定场景的最佳解决方案是什么?
>>> 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
例子:
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
。 但是,它确实有一些限制,因此不清楚它是否是您问题的答案。
一个列表可能多次包含项目并具有特定的顺序。 一套没有。 此外,集合仅适用于可散列对象。
您是在询问子集还是子序列(这意味着您需要一个字符串搜索算法)? 对于许多测试,这两个列表中的任何一个是否相同? 列表中包含哪些数据类型? 就此而言,它是否需要是一个列表?
您的其他帖子与 dict 和 list 相交,使类型更清晰,并且确实得到了使用字典键视图来实现类似集合的功能的建议。 在那种情况下,它的工作原理是众所周知的,因为字典键的行为就像一个集合(以至于在我们在 Python 中使用集合之前,我们使用了字典)。 有人想知道这个问题是如何在三个小时内变得不那么具体的。
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
在丢失元素的第一个实例上all
返回 False 而不必处理每个项目。
假设项目是可散列的
>>> 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) 个项目要迭代和检查。
另一种解决方案是使用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)
我知道它已经很晚了,但只是想用适合我的方法更新答案(Python 3)
# var 1
x = [1,2,3,4]
# var 2
y = [1,2]
# check if var2 is subset of var1
all([z in x for z in y])
干杯。
集合论不适用于列表,因为使用集合论重复会导致错误的答案。
例如:
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
尝试按位AND
>>> set([1,2]) & set([1,2,3])
set([1, 2])
>>> set([0]) & set([1,2,3])
set([])
还没有描述它。
one = [1, 2, 3]
two = [9, 8, 5, 3, 2, 1]
set(x in two for x in one) == set([True])
如果 list1 在列表 2 中:
(x in two for x in one)
生成一个True
列表。
当我们做一个set(x in two for x in one)
只有一个元素(真)。
由于没有人考虑比较两个字符串,这是我的建议。
您当然可能想检查管道(“|”)是否不属于任一列表,并且可能会自动选择另一个字符,但您明白了。
使用空字符串作为分隔符不是解决方案,因为数字可以有多个数字 ([12,3] != [1,23])
def issublist(l1,l2):
return '|'.join([str(i) for i in l1]) in '|'.join([str(i) for i in l2])
如果我参加聚会迟到了,请原谅我。 ;)
为了检查一个set A
是否是set B
子set B
, Python
有A.issubset(B)
和A <= B
。 它适用于set
只有伟大工程,但内部实现的复杂性是未知的。 参考: https : //docs.python.org/2/library/sets.html#set-objects
我想出了一个算法来检查list A
是否是list B
的子集,并带有以下注释。
sort
两个列表进行sort
是合适的。B[j]
的元素值大于第一个列表A[i]
的元素值时,它帮助我break
了loop
。last_index_j
用于在list B
上次停止的位置开始loop
。 它有助于避免从list B
的开头开始比较(您可能猜到这是不必要的,在后续iterations
从index 0
开始list B
) 对两个列表进行排序的复杂度为O(n ln n)
,用于检查子集的复杂度为O(n)
。
O(n ln n) + O(n ln n) + O(n) = O(n ln n)
。
代码有很多print
语句来查看loop
每次iteration
发生了什么。 这些仅用于理解。
检查一个列表是否是另一个列表的子集
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
下面的代码检查给定的集合是否是另一个集合的“适当子集”
def is_proper_subset(set, superset):
return all(x in superset for x in set) and len(set)<len(superset)
在 python 3.5 中,您可以执行[*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))
这是我如何知道一个列表是否是另一个列表的子集,就我而言,顺序对我很重要。
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
大多数解决方案都认为列表没有重复项。 如果您的列表确实有重复项,您可以尝试以下操作:
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
如果您询问一个列表是否“包含”在另一个列表中,则:
>>>if listA in listB: return True
如果您询问 listA 中的每个元素在 listB 中是否具有相同数量的匹配元素,请尝试:
all(True if listA.count(item) <= listB.count(item) else False for item in listA)
如果a2 is subset of a1
,则Length of set(a1 + a2) == Length of set(a1)
a1 = [1, 2, 3, 4, 5];
a2 = [1, 2, 3];
len(set(a1)) == len(set(a1 + a2))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.