我想编写一个函数来确定子列表是否存在于更大的列表中。
list1 = [1,0,1,1,1,0,0]
list2 = [1,0,1,0,1,0,1]
#Should return true
sublistExists(list1, [1,1,1])
#Should return false
sublistExists(list2, [1,1,1])
是否有可以执行此操作的Python函数?
答案 0 :(得分:41)
让我们有点功能,好吗? :)
def contains_sublist(lst, sublst):
n = len(sublst)
return any((sublst == lst[i:i+n]) for i in xrange(len(lst)-n+1))
请注意any()
将在lst内的第一个匹配项上停止 - 如果没有匹配则失败,在O(m * n)ops
答案 1 :(得分:20)
如果您确定您的输入只包含单个数字0和1,那么您可以转换为字符串:
def sublistExists(list1, list2):
return ''.join(map(str, list2)) in ''.join(map(str, list1))
这会创建两个字符串,因此它不是最有效的解决方案,但由于它利用了Python中优化的字符串搜索算法,它可能足以满足大多数目的。
如果效率非常重要,您可以查看适用于列表的Boyer-Moore字符串搜索算法。
天真的搜索有O(n * m)最坏的情况,但如果你不能使用转换为字符串技巧而且你不需要担心性能,那么它可能是合适的。
答案 2 :(得分:4)
我不知道
的功能def sublistExists(list, sublist):
for i in range(len(list)-len(sublist)+1):
if sublist == list[i:i+len(sublist)]:
return True #return position (i) if you wish
return False #or -1
正如马克所说,这不是最有效的搜索(它是O(n * m))。可以通过与字符串搜索非常相似的方式处理此问题。
答案 3 :(得分:3)
有效的方法是使用Boyer-Moore algorithm,正如Mark Byers所说。我已在此处完成了此操作:Boyer-Moore search of a list for a sub-list in Python,但会在此处粘贴代码。它基于维基百科的文章。
search()
函数返回要搜索的子列表的索引,或者失败时返回-1。
def search(haystack, needle):
"""
Search list `haystack` for sublist `needle`.
"""
if len(needle) == 0:
return 0
char_table = make_char_table(needle)
offset_table = make_offset_table(needle)
i = len(needle) - 1
while i < len(haystack):
j = len(needle) - 1
while needle[j] == haystack[i]:
if j == 0:
return i
i -= 1
j -= 1
i += max(offset_table[len(needle) - 1 - j], char_table.get(haystack[i]));
return -1
def make_char_table(needle):
"""
Makes the jump table based on the mismatched character information.
"""
table = {}
for i in range(len(needle) - 1):
table[needle[i]] = len(needle) - 1 - i
return table
def make_offset_table(needle):
"""
Makes the jump table based on the scan offset in which mismatch occurs.
"""
table = []
last_prefix_position = len(needle)
for i in reversed(range(len(needle))):
if is_prefix(needle, i + 1):
last_prefix_position = i + 1
table.append(last_prefix_position - i + len(needle) - 1)
for i in range(len(needle) - 1):
slen = suffix_length(needle, i)
table[slen] = len(needle) - 1 - i + slen
return table
def is_prefix(needle, p):
"""
Is needle[p:end] a prefix of needle?
"""
j = 0
for i in range(p, len(needle)):
if needle[i] != needle[j]:
return 0
j += 1
return 1
def suffix_length(needle, p):
"""
Returns the maximum length of the substring ending at p that is a suffix.
"""
length = 0;
j = len(needle) - 1
for i in reversed(range(p + 1)):
if needle[i] == needle[j]:
length += 1
else:
break
j -= 1
return length
以下是问题中的示例:
def main():
list1 = [1,0,1,1,1,0,0]
list2 = [1,0,1,0,1,0,1]
index = search(list1, [1, 1, 1])
print(index)
index = search(list2, [1, 1, 1])
print(index)
if __name__ == '__main__':
main()
输出:
2 -1
答案 4 :(得分:1)
这种方法适用于比Mark的
稍微脆弱的简单列表def sublistExists(haystack, needle):
def munge(s):
return ", "+format(str(s)[1:-1])+","
return munge(needle) in munge(haystack)
答案 5 :(得分:1)
def sublistExists(x, y):
occ = [i for i, a in enumerate(x) if a == y[0]]
for b in occ:
if x[b:b+len(y)] == y:
print 'YES-- SUBLIST at : ', b
return True
if len(occ)-1 == occ.index(b):
print 'NO SUBLIST'
return False
list1 = [1,0,1,1,1,0,0]
list2 = [1,0,1,0,1,0,1]
#should return True
sublistExists(list1, [1,1,1])
#Should return False
sublistExists(list2, [1,1,1])
答案 6 :(得分:0)
不妨投入@ NasBanov解决方案的递归版本
numpy <= 1.8.2
答案 7 :(得分:0)
def sublist(l1,l2):
if len(l1) < len(l2):
for i in range(0, len(l1)):
for j in range(0, len(l2)):
if l1[i]==l2[j] and j==i+1:
pass
return True
else:
return False
答案 8 :(得分:0)
以下是我最喜欢的简单解决方案(但是,它的野蛮作用,所以我不建议在大数据上使用它):
>>> l1 = ['z','a','b','c']
>>> l2 = ['a','b']
>>>any(l1[i:i+len(l2)] == l2 for i in range(len(l1)))
True
上面的代码实际上创建了所有长度为l2的l1切片,并将它们与l2进行顺序比较。
仅当您不了解它的工作原理(并且想知道)时,才阅读此说明,否则无需阅读
首先,这是您可以遍历l1个项目的索引的方法:
>>> [i for i in range(len(l1))]
[0, 1, 2, 3]
因此,由于 i 表示l1中的项目索引,因此您可以使用它来显示该实际项目,而不是索引号:
>>> [l1[i] for i in range(len(l1))]
['z', 'a', 'b', 'c']
然后从l1创建长度为2的切片(类似于列表中项目的子选择):
>>> [l1[i:i+len(l2)] for i in range(len(l1))]
[['z', 'a'], ['a', 'b'], ['b', 'c'], ['c']] #last one is shorter, because there is no next item.
现在,您可以将每个切片与l2进行比较,然后看到第二个切片匹配:
>>> [l1[i:i+len(l2)] == l2 for i in range(len(l1))]
[False, True, False, False] #notice that the second one is that matching one
最后,使用名为 any 的函数,您可以检查至少一个布尔值是否为True:
>>> any(l1[i:i+len(l2)] == l2 for i in range(len(l1)))
True
答案 9 :(得分:0)
我知道这可能与原始问题不太相关,但如果两个列表中的项目顺序无关紧要,那么对于其他人来说,这可能是非常优雅的 1 行解决方案。如果 List1 元素在 List2 中(无论顺序如何),下面的结果将显示 True。如果订单很重要,则不要使用此解决方案。
List1 = [10, 20, 30]
List2 = [10, 20, 30, 40]
result = set(List1).intersection(set(List2)) == set(List1)
print(result)
输出
True
答案 10 :(得分:-3)
如果我正确理解这一点,你有一个更大的列表,如:
list_A= ['john', 'jeff', 'dave', 'shane', 'tim']
然后还有其他列表
list_B= ['sean', 'bill', 'james']
list_C= ['cole', 'wayne', 'jake', 'moose']
然后我将列表B和C附加到列表A
list_A.append(list_B)
list_A.append(list_C)
所以当我打印list_A
时print (list_A)
我得到以下输出
['john', 'jeff', 'dave', 'shane', 'tim', ['sean', 'bill', 'james'], ['cole', 'wayne', 'jake', 'moose']]
现在我想检查子列表是否存在:
for value in list_A:
value= type(value)
value= str(value).strip('<>').split()[1]
if (value == "'list'"):
print "True"
else:
print "False"
如果你在较大的列表中有任何子列表,这将给你'真'。
答案 11 :(得分:-3)
只需从两个列表中创建集合并使用issubset函数:
def sublistExists(big_list, small_list):
return set(small_list).issubset(set(big_list))