簡體   English   中英

檢查列表是否是子列表

[英]Checking if list is a sublist

我需要檢查 list1 是否是 list2 的子列表(真;如果 list2 中與 list1 相同的每個整數都與 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

任何人都可以幫助我...為什么這不起作用?

我需要檢查 list1 是否是 list2 的子列表(真;如果 list2 中與 list1 相同的每個整數都與 list1 中的索引順序相同)

您的代碼不起作用,因為只要 ls1 中的列表元素沒有出現在 ls2 中,它就會立即返回 False 。

這將創建兩個僅包含公共元素(但按其原始順序)的列表,然后在它們相同時返回 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

編輯:內存高效的變體:

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

檢查列表的所有元素是否都在另一個元素中的一種簡單方法是將兩者都轉換為集合:

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

我們這樣做的另一種方法是使用collections.Counter @L3viathan 的第二個答案是最有效和最快的方法。

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

他的第二種方式快了一個數量級,但我想提到 Counter 變體,因為它在這種情況下的流行和使用。

另一種簡單的方法是使用列表推導並使用內置函數all來驗證 list1 中的所有項都包含在 list2 中。

例子:

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

all(i in list2 for i in list1)

基於 M. Morgan 的回答的內存高效解決方案。 考慮到為了成為子列表,必須在超級列表中以相同的順序找到子列表。

變量k跟蹤匹配字符的長度。 當這與我們的子列表的長度匹配時,我們可以返回 true。

變量s跟蹤起始值。 我跟蹤這一點,以便像sublist(["1", "1", "2"],["0", "1", "1", "1", "2", "1", "2"])與第一個條目的無關重復在不匹配時不會影響當前索引重置。 一旦起始值發生變化s變得無關緊要,因此這種情況不會在模式中間觸發。

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

b = sublista = list然后通過在b長度中拆分 a 來搜索b

例如

>>> 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
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

我發現以上所有發現 ['a','b','d'] 是 ['a','b','c','e','d'] 的子列表,這可能不是盡管子列表的所有元素都存在於列表中,但仍為 true。 所以為了維持秩序,我想出了:

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

雖然這不是很有效的內存,但我發現它在小列表中工作得很好。

def has_ordered_intersection(xs, ys):
    common = {*xs} & {*ys}
    return all(x == y for x, y in zip((x for x in xs if x in common),
                                      (y for y in ys if y in common)))

這通過了@L3viathan 的 doctest,代碼行更少,使用類似於“內存高效變體”的策略,並且可以說整體效率更高。

>>> has_ordered_intersection([], [1,2,3])
True
>>> has_ordered_intersection([1,2,3,4], [2,5,3])
True
>>> has_ordered_intersection([1,2,3,4], [0,3,2])
False
>>> has_ordered_intersection([1,2,3,4], [1,2,5,6,7,8,5,76,4,3])
False

我用了交集,而不是一台發電機,因為我覺得額外的內存是一個很好的權衡比較的時間成本快捷掃描每個元素的整個列表(什么in做一個列表),特別是當它們長。

我也不認為這應該被稱為“子列表”,因為允許xs具有ys沒有的元素。 上述關系是對稱的:交換參數不會改變答案。 真正有序的“子列表”不會是對稱的,看起來更像這樣

def is_ordered_sublist(xs, ys):
    xset = {*xs}
    return all(x == y for x, y in zip(xs, (y for y in ys if y in xset)))

使用迭代器很容易。

>>> 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

試試這個!! 子列表 y 不缺少列表 x 的序列。

x= 列表

y=子列表

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")

我想出了一個簡短的方法來檢查子列表

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))

我所做的基本上是取 2 個列表 lst1 是較大的列表,而 lst2 是我們正在檢查的子列表。 然后我取 lst2 的每個元素並通過查找它的索引來檢查它是否在 lst1 中

如果它甚至找不到單個項目,它 ..returns False

如果所有項目都被覆蓋,則返回 True

另一種方法是遍歷所有可能的子列表並在找到匹配項后返回

def is_sublist(ys, xs):
    for i in range(len(xs) - len(ys)):
        if xs[i:i + len(ys)] == ys:
            return True
    return False

在 l1 中查找元素與 l2 中的第一個元素匹配的所有索引,然后我遍歷此索引列表,並為每個元素獲取 l1 的切片,其長度與 l2 相同。 如果 l1 切片等於 l2,則 l2 是 l1 的子列表

前任:

l1 = [1,2,3,2,1,1,3,3,4,5]

l2 = [2,1,1,3,3]

真的

l1 = [1,2,3,2,1,3,3,4,5]

l2 = [2,1,1,3,3]

錯誤的

def is_sublist(l1, l2):
    index_list = [i for i, v in enumerate(l1) if v==l2[0]]
    for ii in index_list:
        l1_slice = l1[ii:ii+len(l2)]
        if l1_slice == l2:
            return True
    else:
        return False

以下有什么問題:

def sublist(lst1, lst2):
return all([(x in lst2) for x in lst1])

如果對於 lst1 中的所有項目,每個項目都存在於 lst2 中,則將返回 true

def lis1(item,item1):
    sub_set = False
    for x in range(len(item)):
     if item[x] == item1[0]:
         n = 1
         while (n < len(item1) and (item[x + n] == item1[1])):
             n += 1
             if n == len(item1):
                 return True
    return False
a = [2,3,4,5,6]
b = [5,6]
c = [2,7,6]
print(lis1(a,b))
print(lis1(a,c))
#list1 = ['1','2',"4"]############works
#list2 = ['1','2',3]

lst2 = [4,8,9,33,44,67,123]
lst1 = [8,33,7] # works!


def sublist(lst1, lst2):
    'checks whether list lst1 is a sublist of list lst2'
    index1 = 0  # lst1 index
    index2 = 0  # lst2 index

    # go through indexes of lst1
    while index1 < len(lst1):

        # search for item in lst2 matching item in lst1 at index index1
        while index2 < len(lst2) and lst1[index1] != lst2[index2]:
            index2 += 1

        # if we run out of items in lst2, lst1 is not a sublist of lst2
        if index2 == len(lst2):
            return False
        index1 += 1

    # every item in lst1 has been matched to an item in lst2, from left to right
    return True

print( sublist(lst1, lst2))

我需要知道第一個列表是否是第二個列表的子列表。 這個訂單對我很重要。 我已經嘗試了一些解決方案,但它們對於我的需求來說太“通用”了。 我還想確保兩個列表不相等。 這是解決方案。

def sublist(lst1, lst2):
    len1 = len(lst1)
    len2 = len(lst2)

    if len1 >= len2:
        return False

    for i in range(0, len1):
        if lst1[i] != lst2[i]:
            return False

    return True

在我們進行比較時,只使用沿着 list2 運行的索引怎么樣?

def is_ordered_sublist(lst1: list, lst2: list) -> bool:
""" Checks if lst1 is an ordered sublist of lst2 """

    try:
        index = 0
        for item in lst1:
            location = lst2[index:].index(item)
            index += location + 1
        return True
    except ValueError:
        return False

基本上對於 list1 中的每個項目,它只是找到它出現在第二個列表中的第一個索引。 此后它只需要考慮 list2 的其余部分。 所以更糟糕的情況復雜度是簡單的 O(len(list2))。

此代碼嘗試通過掃描 list2 在 list2 中查找 list1。 它在 list2 中搜索 list1 中的第一項,然后檢查 list1 中的后續項是否也與 list2 中找到第一項的位置匹配。 如果 list1 中的前 2/4 項在 list2 中的某個位置匹配,但第 3 項不匹配,則不會花時間比較第 4 項。

def ordered_sublist(l1, l2):
    length = len(l1)
    for i in range(len(l2) - length + 1):
        if all(l1[j] == l2[j + i] for j in range(length)):
            return True
    return False

我認為這是解決這個問題的最好方法。 這將檢查list1是否是list2的子列表。 我們將假設所有元素都是唯一的。 如果我們有重復的元素,下面的代碼只會確保list1每個元素都包含在list2 因此,我們不考慮多重性。

list1 = [2, 3, 3, 4, 5, 9]
list2 = [1, 2, 3, 4, 5, 6, 7, 8, 9]

set(list1).issubset(set(list2))

列表是數據結構,其中元素的順序很重要。

我知道這個問題明確指定了“索引的相同順序”,但一般來說,當您說“子列表”時,這不一定是唯一適用的限制。 每個元素之間的相對位置也可能是一個限制。

在我的特殊情況下 list1=[1,2,3,4] list2=[1,2,4] 並且 list2 不是 list1 的子列表,但 list3=[2,3,4] 是 list1 的子列表。

只是為了完成,我在這里發布我的代碼來查找子列表,其中每個元素的相對索引也應該保留。

def is_sublist(list1, list2):
    first_index = -1
    for i in range(len(list1)):
        if first_index>=0:
            j = i-first_index
            if list1[i] != list2[j]:
                return False
            if j == len(list2)-1:
                return True
         elif list1[i] == list2[0]:
            first_index = i
    return False
print(is_sublist(['r1','r2','r3','r4','r6'],['r1','r2','r3']))
#>> True
print(is_sublist(['r1','r2','r3','r4','r6'],['r2','r3','r4']))
#>> True
print(is_sublist(['r1','r2','r3','r4','r6'],['r1','r2','r4']))
#>> False

定義:

  • 如果 A的元素確切序列存在於 B 中,則列表 A 是列表 B 的子列表。
  • 空列表是任何列表的子列表。

以下函數返回list_a中第一次出現list_alist_b ,否則返回-1 對於空的list_a ,返回0

def sublist(list_a, list_b):
    if 0 == len(list_a):
        return 0

    if len(list_b) < len(list_a):
        return -1

    idx = -1
    while list_a[0] in list_b[idx+1:]:
        idx = list_b.index(list_a[0], idx + 1)
        if list_a == list_b[idx:idx+len(list_a)]:
            return idx

    return -1

一些測試:

>>> sublist([], [])
0
>>> sublist([], [1, 2, 3])
0
>>> sublist([3, 6], [1, 2, 3, 6, 3, 7, 9, 8, 0, 3, 6])
2
>>> sublist([3, 7, 9, 8], [1, 2, 3, 6, 3, 7, 9, 8, 0, 3, 6])
4
>>> sublist([3, 6, 3, 7, 9, 8, 0, 3, 6], [1, 2, 3, 6, 3, 7, 9, 8, 0, 3, 6])
2
>>> sublist([1, 2, 3, 6, 3, 7, 9, 8, 0, 3, 6, 4], [1, 2, 3, 6, 3, 7, 9, 8, 0, 3, 6])
-1
>>> sublist([3, 7, 4], [1, 2, 3, 6, 3, 7, 9, 8, 0, 3, 6])
-1

這是一個惰性迭代的通用版本,用於檢查一個可迭代對象是否是另一個可迭代對象的子序列:

from typing import Iterable

def is_subsequence(a: Iterable, b: Iterable) -> bool:
    b_iterator = iter(b)
    for x in a:
        for y in b_iterator:
            if y == x:
                break
        else:
            return False
    else:
        return True

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM