我试图以最有效的方式来确定List1=[0,0,0]
包含在List2
或List3
中,以及在哪里:
List2=[34, 32, 25, 0, 0, 0, 32]
的结果为真
List3=[34, 32, 25, 0, 32, 0, 0]
的结果为 False
我尝试了set().subset
,但返回了 True 和 True ,我尝试了if List1 in List2
并得到了 False < / p>
我知道我可以遍历列表并进行值,序列比较,但是想知道是否已经有一个函数可以进行这种比较,如果不能,可以使用一个相当简单的lambda表达式来完成?
注意:List2
和List3
可能会更长一些,这些只是显示差异的简短示例,更确切地说是我要寻找的内容
答案 0 :(得分:2)
我不知道为此设计的功能。但是,您可以使用lambda来实现。
is_contiguous_subsequence = lambda small, big: any(small == big[i:i+len(small)] for i in range(len(big) - len(small) + 1))
根据我的口味,lambda函数中包含的字符太多,因此建议将其设为常规函数。
def is_contiguous_subsequence(small, big):
return any(small == big[i:i+len(small)] for i in range(len(big) - len(small) + 1))
根据any
的性质,这将在找到第一个匹配项时返回True,而不继续进行big
列表的其余部分。只是一点点效率奖励。
答案 1 :(得分:1)
正如一些评论所指出的那样,可读性和效率之间存在着张力。此解决方案提供较大列表中较小列表的索引,并且可以通过检查索引是否不是None
来解决您的问题。
对于较小的父列表(长度为6),以下算法比更直接的解决方案快约2倍,而对于较长的列表(长度为10,000),以下算法可以快约15倍。
技巧是在每个项目上使用内置的list.index()
函数来快速跳过父级列表。如果我们发现索引之间的任何大于1的间隔,我们都知道该序列已中断,但是无论它在哪里,我们都可以在此点附近开始。
def index_of(parent_list, sub_list):
# No match possible
if len(sub_list) > len(parent_list):
return
# Empty list 'matches' at index 0
if not sub_list:
return 0
sequence_start = 0
while True:
try:
match_found, offset = _sub_match(
parent_list, sub_list, sequence_start)
except ValueError:
return
if match_found:
return sequence_start
sequence_start = offset
def _sub_match(parent_list, sub_list, start_at):
pos, last_offset = 0, start_at - 1
# Skip through the items looking for the next index after the one before
for item in sub_list:
offset = parent_list.index(item, last_offset + 1)
# We jumped more than one value, so the sequence is broken
if offset - last_offset != 1:
return False, offset - pos
pos += 1
last_offset = offset
return True, last_offset
答案 2 :(得分:1)
首先感谢@brentertainer和@ jon-betts的见解。现在,我要重申的是,SubList是否仍包含在FullList中,因此我在@ jon-betts发布的内容中看到了效率的提高,但改为如下实现:
class ClassContainer:
# This handles everything pertinent to this Class
def __init__(self):
self.ClassName = 'ThisClass'
@staticmethod
def IsSubSet(SubList, FullList):
RetVal = False
Item = SubList[0]
Range = len(FullList) - len(SubList)
LenAdjtr = len(SubList)
for idx in range ( Range ):
idx = FullList.index(Item, idx)
if idx > Range:
break
if FullList[idx:(idx + LenAdjtr)] == SubList:
RetVal = True
break
return RetVal
对于较长的序列,这无疑可以极大地简化该功能,该序列对于此应用程序非常有用,但它本身并不关心通过SubList进行挑剔,只是对其全部值进行了直接比较,这似乎更加有效。
答案 3 :(得分:0)
这是功能编程方式:
List1 = [0, 0, 0]
List2 = [34, 32, 25, 0, 0, 0]
f = lambda *args: True if \
list(filter(lambda i: i in args[1] and \
args[0].count(i) <= args[1].count(i), args[0])) == args[0] else False
print(f(List1, List2))
# True
答案 4 :(得分:0)
我喜欢这种方式,定义了一个返回生成器的方法:
def each_cons(ary, n = 2):
if n < 2: n = 1
i, size = 0, len(ary)
while i < size-n+1:
yield ary[i:i+n]
i += 1
然后您可以像这样使用
:list2= = [34, 32, 25, 0, 0, 0, 32]
chk = [0,0,0]
chk in each_cons(list2, len(chk))
#=> True
res = each_cons(list2, 3)
print(list(res))
#=> [[34, 32, 25], [32, 25, 0], [25, 0, 0], [0, 0, 0], [0, 0, 32]]