Je veux écrire une fonction qui détermine si une sous-liste existe dans une liste plus grande.
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])
Existe-t-il une fonction Python capable de le faire?
Si vous êtes certain que vos entrées ne contiendront que les chiffres uniques 0 et 1, vous pouvez convertir en chaînes:
def sublistExists(list1, list2):
return ''.join(map(str, list2)) in ''.join(map(str, list1))
Cela crée deux chaînes, ce n'est donc pas la solution la plus efficace, mais comme il tire parti de l'algorithme de recherche de chaînes optimisé de Python, il est probablement suffisant pour la plupart des applications.
Si l'efficacité est très importante, vous pouvez utiliser l'algorithme de recherche de chaînes Boyer-Moore , adapté au travail sur les listes.
Une recherche naïve a O (n * m) le pire des cas, mais peut convenir si vous ne pouvez pas utiliser le tour de conversion en chaîne et que vous n'avez pas à vous soucier des performances.
Soyons un peu fonctionnels, allons-nous? :)
def contains_sublist(lst, sublst):
n = len(sublst)
return any((sublst == lst[i:i+n]) for i in xrange(len(lst)-n+1))
Notez que any()
s'arrêtera lors du premier match de sous-match dans lst - ou échouera s'il n'y a pas de correspondance, après O (m * n) ops
Aucune fonction que je connaisse
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
Comme Mark l’a noté, ce n’est pas la recherche la plus efficace (c’est O (n * m)). Ce problème peut être abordé de la même manière que la recherche de chaînes.
Le moyen le plus efficace consiste à utiliser l’algorithme de Boyer-Moore , comme le suggère Mark Byers. Je l'ai déjà fait ici: Boyer-Moore recherche une liste pour une sous-liste en Python , mais je vais coller le code ici. Il est basé sur l'article de Wikipedia.
La fonction search()
renvoie l'index de la sous-liste recherchée ou -1 en cas d'échec.
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
Voici l'exemple de la question:
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 __== '__main__':
main()
Sortie:
2 - 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])
Voici un moyen qui fonctionnera pour des listes simples qui est légèrement moins fragile que Mark
def sublistExists(haystack, needle):
def munge(s):
return ", "+format(str(s)[1:-1])+","
return munge(needle) in munge(haystack)
Peut-être aussi jeter une version récursive de la solution de @ NasBanov
def foo(sub, lst):
'''Checks if sub is in lst.
Expects both arguments to be lists
'''
if len(lst) < len(sub):
return False
return sub == lst[:len(sub)] or foo(sub, lst[1:])
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