web-dev-qa-db-fra.com

Vérifier si la liste est une sous-liste

Je dois vérifier si list1 est une sous-liste de list2 (vrai; si chaque entier de list2 commun à list1 est dans le même ordre d'index que dans list1)

def sublist(lst1,lst2):
    for i in range(len(lst1)):
        if lst1[i] not in lst2:
            return False
        for j in range(len(lst2)):
            if (lst1[j] in lst2) and (lst2.index(lst1[i+1]) > lst2.index(lst1[i])):
                return True

Quelqu'un peut-il m'aider ... pourquoi ça ne marche pas?

13
MMM

je dois vérifier si list1 est une sous-liste de list2 (vrai; si chaque entier de list2 commun à list1 est dans le même ordre d'index que dans list1)

Votre code ne fonctionne pas car dès qu'un élément de liste dans ls1 ne se produit pas dans ls2, il renvoie immédiatement False.

Cela crée deux listes qui ne contiennent que les éléments communs (mais dans leur ordre d'origine), puis renvoie True lorsqu'elles sont identiques:

def sublist(lst1, lst2):
   ls1 = [element for element in lst1 if element in lst2]
   ls2 = [element for element in lst2 if element in lst1]
   return ls1 == ls2

edit: Une variante économe en mémoire:

def sublist(ls1, ls2):
    '''
    >>> sublist([], [1,2,3])
    True
    >>> sublist([1,2,3,4], [2,5,3])
    True
    >>> sublist([1,2,3,4], [0,3,2])
    False
    >>> sublist([1,2,3,4], [1,2,5,6,7,8,5,76,4,3])
    False
    '''
    def get_all_in(one, another):
        for element in one:
            if element in another:
                yield element

    for x1, x2 in Zip(get_all_in(ls1, ls2), get_all_in(ls2, ls1)):
        if x1 != x2:
            return False

    return True
6
L3viathan

Solution efficace en mémoire basée sur la réponse de M. Morgan. Prend en compte que pour être une sous-liste, la sous-liste doit être trouvée dans le même ordre dans la super-liste.

La variable k garde la trace de la longueur des caractères correspondants. Lorsque cela correspond à la longueur de notre sous-liste, nous pouvons renvoyer true.

La variable s garde la trace de la valeur de départ. Je garde cette trace de sorte qu'un scénario de test tel que sublist(["1", "1", "2"],["0", "1", "1", "1", "2", "1", "2"]) avec répétitions superflues de la première entrée n'affecte pas la réinitialisation actuelle de l'index lorsqu'elle n'est pas appariée. Une fois que la valeur de départ change, la variable s devient inutile, de sorte que ce cas ne se déclenche pas au milieu d'un motif.

def sublist(sublist, lst):
    if not isinstance(sublist, list):
        raise ValueError("sublist must be a list")
    if not isinstance(lst, list):
        raise ValueError("lst must be a list")

    sublist_len = len(sublist)
    k=0
    s=None

    if (sublist_len > len(lst)):
        return False
    Elif (sublist_len == 0):
        return True

    for x in lst:
        if x == sublist[k]:
            if (k == 0): s = x
            Elif (x != s): s = None
            k += 1
            if k == sublist_len:
                return True
        Elif k > 0 and sublist[k-1] != s:
            k = 0

    return False
2
Dave Thomas

Un moyen simple de vérifier si tous les éléments d’une liste se trouvent dans un autre consiste à convertir les deux en ensembles:

def sublist(lst1, lst2):
    return set(lst1) <= set(lst2)

Une autre façon de procéder consiste à utiliser collections.Counter. La deuxième réponse de @ L3viathan est le moyen le plus efficace et le plus rapide de le faire.

def sublist1(lst1, lst2):
    ls1 = [element for element in lst1 if element in lst2]
    ls2 = [element for element in lst2 if element in lst1]
    return ls1 == ls2


def sublist2(lst1, lst2):
    def get_all_in(one, another):
        for element in one:
            if element in another:
                yield element
    for x1, x2 in Zip(get_all_in(lst1, lst2), get_all_in(lst2, lst1)):
        if x1 != x2:
            return False
    return True


def sublist3(lst1, lst2):
    from collections import Counter
    c1 = Counter(lst1)
    c2 = Counter(lst2)
    for item, count in c1.items():
        if count > c2[item]:
            return False
    return True


l1 = ["a", "b", "c", "c", "c", "d", "e"]
l2 = ["c", "a", "c", "b", "c", "c", "d", "d", "f", "e"]

s1 = lambda: sublist1(l1, l2)
s2 = lambda: sublist2(l1, l2)
s3 = lambda: sublist3(l1, l2)

from timeit import Timer
t1, t2, t3 = Timer(s1), Timer(s2), Timer(s3)
print(t1.timeit(number=10000))  # => 0.034193423241588035
print(t2.timeit(number=10000))  # => 0.012621842119714115
print(t3.timeit(number=10000))  # => 0.12714286673722477

Son 2ème chemin est plus rapide d'un ordre de grandeur, mais je voulais mentionner la variante Counter en raison de sa prévalence et de son utilisation en dehors de ce scénario.

2
Goodies

C'est facile avec les itérateurs. 

>>> a = [0,1,2]
>>> b = [item for item in range(10)]
>>> b
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a
[0, 1, 2]
>>> [False, True][set([item in b for item in a]) == set([True])]
True
>>> a = [11, 12, 13]
>>> [False, True][set([item in b for item in a]) == set([True])]
False
1
Umair Bhatti

b = sublist et a = list puis recherchez b en divisant a en longueurs de b

par exemple.

>>> a = [2,4,3,5,7] , b = [4,3]
>>> b in [a[i:len(b)+i] for i in xrange(len(a))]
True

>>> a = [2,4,3,5,7] , b = [4,10]
>>> b in [a[i:len(b)+i] for i in xrange(len(a))]

False
1
codename47

J'ai trouvé que tout ce qui précède ['a', 'b', 'd'] est une sous-liste de ['a', 'b', 'c', 'e', ​​'d'], qui ne peuvent pas être vrai bien que tous les éléments de la sous-liste soient présents dans la liste. Donc pour maintenir l'ordre et je suis venu avec:

def sublist4(sublist,lst):
    #Define an temp array to populate 
    sub_list=[]
    comparable_sublist=[]
    #Define two constants to iterate in the while loop
    i=0
    k=0
    #Loop the length of lst
    while i < len(lst):
        #If the element is in the sublist append to temp array, 
        if k < len(sublist) and lst[i] == sublist[k]:
            sub_list.append(lst[i])
            #set a comparable array to the value of temp array
            comparable_sublist = sub_list
            k += 1
            #If the comparable array is the same as the sublist, break
            if len(comparable_sublist) == len(sublist):
                break

        #If the element is not in the sublist, reset temp array
        else:
            sub_list = []


        i += 1

    return comparable_sublist == sublist

Bien que la mémoire utilisée ne soit pas très efficace, je trouve que cela fonctionne assez bien avec les petites listes.

1
M. Morgan
def sublist(l1,l2):
    s1=" ".join(str(i) for i in l1)
    s2=" ".join(str(i) for i in l2)
    if s1 in s2:
        return True
    else:
        return False
0
Sanjana Mantri

Je suis venu avec un moyen court pour vérifier la sous-liste

lst1=[1,2,5,6,8,3,2,34,3,4]
lst2=[1,2,3,4]


def sublist(lst1,lst2):
    for item in lst2:
        try:
           lst1.index(item)
        except ValueError:
           return False
     return True


 print(sublist(lst1,lst2))

ce que j’ai fait, c’est essentiellement prendre 2 listes lst1 est la plus grande liste et lst2 est la sous-liste que nous recherchons . alors je prends chaque élément du lst2 et vérifie s’il se trouve dans le lst1 en recherchant son index 

s'il ne trouve même pas un seul objet, il retourne Faux

si tous les éléments sont couverts, la valeur renvoyée est True 

0
Mohan Ram

Essaye celui-là!! la sous-liste y ne manque pas à la séquence de la liste x.

x = liste 

y = sous-liste

if ([i for i,j in enumerate(y) for k,l in enumerate(x) if i == k and j!=l]):
    print("True")
else:
    print("False")
0
Vishal Khichadiya

Un autre moyen simple consiste à utiliser list comprehension Et utilisez la fonction intégrée all pour vérifier que tous les éléments de list1 figurent dans list2.

Exemple:

list1 = ['1','2']
list2 = ['1','2',3]

all(i in list2 for i in list1)
0
Geislor Crestani