检查列表是否是子列表

时间:2016-03-12 22:35:05

标签: python python-2.7 python-3.x

我需要检查list1是否是list2的子列表(True;如果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

任何人都可以帮助我......为什么这不起作用?

24 个答案:

答案 0 :(得分:6)

  

我需要检查list1是否是list2的子列表(True;如果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

答案 1 :(得分:3)

我们这样做的另一种方式是使用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变体,因为它在这种情况之外的流行和使用。

答案 2 :(得分:2)

检查列表的所有元素是否在其他元素中的简单方法是将两者都转换为集合:

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

答案 3 :(得分:2)

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

答案 4 :(得分:2)

b = sublista = list,然后通过拆分长度b

来搜索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

答案 5 :(得分:1)

我发现以上都发现['a','b','d']是['a','b','c','e','d']的子列表,尽管子列表中的所有元素都存在于列表中,但可能并非如此。所以为了维持秩序,我提出了:

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

虽然这不是非常有效的内存,但我发现它适用于小型列表。

答案 6 :(得分:1)

使用迭代器很容易。

Processor p = new Processor(false);
Serializer s = p.newSerializer(System.out);
s.setOutputProperty(Property.STANDALONE, "no");
XmlStreamWriter writer = s.getXmlStreamWriter();

答案 7 :(得分:1)

我认为这是解决此问题的最佳方法。这将检查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))

答案 8 :(得分:1)

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

答案 9 :(得分:1)

以下是什么问题:

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

如果对于lst1中的所有项目,每个项目都存在于lst2中,则将返回true

答案 10 :(得分:1)

在l1中查找元素与l2中的第一个元素匹配的所有索引,然后循环遍历此索引列表,并为每个元素获取具有l2相同长度的l1的切片。如果l1 slice等于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

答案 11 :(得分:0)

这是一个惰性迭代的通用版本,用于检查一个可迭代对象是否是另一个可迭代对象的子序列:

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

答案 12 :(得分:0)

定义:

  • 如果 A 的元素的精确序列存在于 B 中,则列表 A 是列表 B 的子列表。
  • 空列表是任何列表的子列表。

以下函数返回list_a中第一次出现list_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

答案 13 :(得分:0)

列表是其中元素顺序重要的数据结构。

我知道这个问题明确指定了“索引的相同顺序”,但是通常来说,当您说“子列表”时,这不一定是唯一适用的限制。每个元素之间的相对位置也可能是一个限制。

在我的特定情况下,list1 = [1,2,3,4] list2 = [1,2,4]并且list2不是list1的子列表,但是list3 = [2,3,4]是以下子列表清单1。

为了完整起见,我在这里发布我的代码以查找子列表,其中还应保留每个元素的相对索引。

{{1}}

答案 14 :(得分:0)

此代码尝试通过扫描list2在list2中找到list1。它在list2中搜索list1中的第一项,然后检查list1中的后续项在list2中找到第一项的位置是否也匹配。如果list1中的前2/4个项目在list2中的某个位置处匹配,但第3个不匹配,则它将不花时间比较第4个。

def create_grid(grid):
  
  grid = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
  
  return grid

答案 15 :(得分:0)

在进行比较时,仅使用沿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

基本上,对于列表1中的每个项目,它只是找到出现在第二个列表中的第一个索引。此后,只需要考虑list2的其余部分。因此,最糟糕的情况是简单的O(len(list2))。

答案 16 :(得分:0)

我需要知道第一个列表是否是第二个列表的子列表。这个命令对我很重要。我已经尝试了一些解决方案,但是对于我的需求而言,它们太“通用”了。我还想确保两个列表不相等。这是解决方案。

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

答案 17 :(得分:0)

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

答案 18 :(得分:0)

另一种方法是遍历所有可能的子列表,并在找到匹配项后返回

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

答案 19 :(得分:0)

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

答案 20 :(得分:0)

我想出了一种方法来检查子列表

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中

如果找不到单个项目,则返回False

如果所有项目均已覆盖,则返回True

答案 21 :(得分:0)

试试这个!!子列表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")

答案 22 :(得分:0)

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

答案 23 :(得分:0)

另一种简单方法是使用list comprehension 并使用内置函数all来验证list1中的所有项都包含在list2中。

示例:

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

all(i in list2 for i in list1)