Python >> Python tutoriál >  >> Python

Kontrola, zda je seznam podseznamem

Potřebuji zkontrolovat, zda je seznam1 podseznamem k seznamu2 (Pravda; pokud každé celé číslo v seznamu2, které je společné se seznamem1, je ve stejném pořadí indexů jako v seznamu1)

Váš kód nefunguje, protože jakmile se prvek seznamu v ls1 nevyskytuje v ls2, okamžitě vrátí hodnotu False.

Tím se vytvoří dva seznamy, které obsahují pouze společné prvky (avšak v původním pořadí), a když jsou stejné, vrátí hodnotu True:

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

upravit: Paměťově efektivní varianta:

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

Dalším způsobem, jak to udělat, je collections.Counter . Druhá odpověď @L3viathan je nejúčinnější a nejrychlejší způsob, jak to udělat.

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

Jeho 2. cesta je řádově rychlejší, ale chtěl jsem zmínit variantu Counter kvůli jejímu rozšíření a použití mimo tento scénář.


Snadný způsob, jak zkontrolovat, zda jsou všechny prvky seznamu v jiném, je převod obou na sady:

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