【发布时间】:2010-04-06 05:52:49
【问题描述】:
是否有任何内置函数可以检查一个列表是否包含在另一个列表中而不进行任何循环?
我在dir(list) 中寻找过,但没有发现任何有用的东西。
【问题讨论】:
是否有任何内置函数可以检查一个列表是否包含在另一个列表中而不进行任何循环?
我在dir(list) 中寻找过,但没有发现任何有用的东西。
【问题讨论】:
取决于“包含”的含义。也许是这样:
if set(a) <= set(b):
print("a is in b")
【讨论】:
sub 的调用是线性的,但<= 不能是免费的。我错过了什么吗?
set 是哈希表。因此访问set 中的对象的成本是O(1)。在这段代码中,您必须遍历set(a) (O(len(set(a))) 中的所有元素并检查该元素是否在set(b) (O(1)) 中。但是,我们当然不会(O(len(sublist)))总体花费我们,因为这些集合必须首先从列表中构建。我不确定这要花多少钱,但我认为应该是O(len(list)),所以总成本是O(len(a)) + O(len(b)) + O(len(set(a))
sub 是 set 的脑残。)
a = [1,1,2,3] 和 b=[1,2,3] 怎么办? a 不包含在 b 中,但您的代码是这样写的。
假设你想查看sublist的所有元素是否也是superlist的元素:
all(x in superlist for x in sublist)
【讨论】:
您可能想使用set
if set(a).issubset(b):
print('a is contained in b')
【讨论】:
lists 都转换为sets。因此,我的建议节省了一条指令(我已经检查过dis.dis())。此外,由于issubset 方法的冗长,它更具可读性。
解决方案取决于您对列表的期望值。
如果存在重复值的可能性,并且您需要检查测试容器中是否有足够的值,那么这是一个时间效率低的解决方案:
def contained(candidate, container):
temp = container[:]
try:
for v in candidate:
temp.remove(v)
return True
except ValueError:
return False
使用以下方法测试此功能:
>>> a = [1,1,2,3]
>>> b = [1,2,3,4,5]
>>> contained(a,b)
False
>>> a = [1,2,3]
>>> contained(a,b)
True
>>> a = [1,1,2,4,4]
>>> b = [1,1,2,2,2,3,4,4,5]
>>> contained(a,b)
True
当然,这个解决方案可以大大改进:list.remove() 可能很耗时,可以通过巧妙的排序和索引来避免。但我不知道如何在这里避免循环......
(无论如何,任何其他解决方案都将使用集合或列表理解来实现,它们在内部使用循环......)
【讨论】:
如果您想验证 list1 中的所有项目都在 list2 上,您可以执行以下列表理解:
all(elem in list1 for elem in list2)
您也可以将 list1 和 list2 直接替换为将返回该列表的代码
all([snack in ["banana", "apple", "lemon", "chocolate", "chips"] for snack in ["chips","chocolate"])
任何 + 列表理解都可以翻译成这个,以便更好地理解代码
return_value = False
for snack in snacks:
if snack in groceries:
return_value = True
else:
return_value = False
【讨论】: