python列表是否包含_使用Python测试列表是否包含另一个列表

使用Python测试列表是否包含另一个列表

如何测试一个列表是否包含另一个列表(即它是连续的子序列)。 假设有一个名为contains的函数:

contains([1,2], [-1, 0, 1, 2]) # Returns [2, 3] (contains returns [start, end])

contains([1,3], [-1, 0, 1, 2]) # Returns False

contains([1, 2], [[1, 2], 3]) # Returns False

contains([[1, 2]], [[1, 2], 3]) # Returns [0, 0]

编辑:

contains([2, 1], [-1, 0, 1, 2]) # Returns False

contains([-1, 1, 2], [-1, 0, 1, 2]) # Returns False

contains([0, 1, 2], [-1, 0, 1, 2]) # Returns [1, 3]

13个解决方案

50 votes

如果所有项目都是唯一的,则可以使用集合。

>>> items = set([-1, 0, 1, 2])

>>> set([1, 2]).issubset(items)

True

>>> set([1, 3]).issubset(items)

False

Thomas O answered 2020-07-27T14:02:46Z

17 votes

这是我的版本:

def contains(small, big):

for i in xrange(len(big)-len(small)+1):

for j in xrange(len(small)):

if big[i+j] != small[j]:

break

else:

return i, i+len(small)

return False

正如安德鲁·贾菲(Andrew Jaffe)在他的评论中指出的那样,它返回一个元组(start,end + 1),因为我认为这更像pythonic。 它不会切片任何子列表,因此应该合理有效。

新手感兴趣的一点是,它使用了for语句上的else子句-这不是我经常使用的东西,但是在这种情况下是非常有价值的。

这与在字符串中查找子字符串相同,因此对于大型列表,实现类似Boyer-Moore算法的方法可能更有效。

Dave Kirby answered 2020-07-27T14:02:23Z

15 votes

有all()和any()函数可以执行此操作。检查list1是否包含list2中的所有元素

result = all(elem in list1 for elem in list2)

检查list1是否在list2中包含ANY元素

result = any(elem in list1 for elem in list2)

变量结果将为布尔值(TRUE / FALSE)。

ericyan3000 answered 2020-07-27T14:03:15Z

4 votes

如果big列表确实很大,我可以谦虚地建议使用Rabin-Karp算法。 该链接甚至包含在几乎Python中几乎可用的代码。

9000 answered 2020-07-27T14:03:36Z

3 votes

编辑OP之后:

def contains(small, big):

for i in xrange(1 + len(big) - len(small)):

if small == big[i:i+len(small)]:

return i, i + len(small) - 1

return False

eumiro answered 2020-07-27T14:03:56Z

2 votes

由于它使用内置的list.index()方法和==运算符进行线性搜索,因此该方法有效并且相当快:

def contains(sub, pri):

M, N = len(pri), len(sub)

i, LAST = 0, M-N+1

while True:

try:

found = pri.index(sub[0], i, LAST) # find first elem in sub

except ValueError:

return False

if pri[found:found+N] == sub:

return [found, found+N-1]

else:

i = found+1

martineau answered 2020-07-27T14:04:16Z

1 votes

这是使用列表方法的简单算法:

#!/usr/bin/env python

def list_find(what, where):

"""Find `what` list in the `where` list.

Return index in `where` where `what` starts

or -1 if no such index.

>>> f = list_find

>>> f([2, 1], [-1, 0, 1, 2])

-1

>>> f([-1, 1, 2], [-1, 0, 1, 2])

-1

>>> f([0, 1, 2], [-1, 0, 1, 2])

1

>>> f([1,2], [-1, 0, 1, 2])

2

>>> f([1,3], [-1, 0, 1, 2])

-1

>>> f([1, 2], [[1, 2], 3])

-1

>>> f([[1, 2]], [[1, 2], 3])

0

"""

if not what: # empty list is always found

return 0

try:

index = 0

while True:

index = where.index(what[0], index)

if where[index:index+len(what)] == what:

return index # found

index += 1 # try next position

except ValueError:

return -1 # not found

def contains(what, where):

"""Return [start, end+1] if found else empty list."""

i = list_find(what, where)

return [i, i + len(what)] if i >= 0 else [] #NOTE: bool([]) == False

if __name__=="__main__":

import doctest; doctest.testmod()

jfs answered 2020-07-27T14:04:36Z

1 votes

如果我们在讨论测试一个列表是否包含另一个列表作为顺序时解决问题,那么答案可能是下一个:

def contains(subseq, inseq):

return any(inseq[pos:pos + len(subseq)] == subseq for pos in range(0, len(inseq) - len(subseq) + 1))

在这里,我使用单元测试来调整此一线:

[HTTPS://gist.GitHub.com/Anonymous/6910啊85不4978打呃呃137发]

Oleksiy answered 2020-07-27T14:05:07Z

1 votes

最小的代码:

def contains(a,b):

str(a)[1:-1].find(str(b)[1:-1])>=0

Bart Mensfort answered 2020-07-27T14:05:27Z

1 votes

这是我的答案。 此功能将帮助您找出B是否为A的子列表。时间复杂度为O(n)。

`def does_A_contain_B(A, B): #remember now A is the larger list

b_size = len(B)

for a_index in range(0, len(A)):

if A[a_index : a_index+b_size]==B:

return True

else:

return False`

Akila D. Perera answered 2020-07-27T14:05:47Z

0 votes

我试图使它尽可能高效。

它使用发电机; 建议那些不熟悉这些野兽的人检查他们的文件以及收益表述。

基本上,它从子序列中创建值的生成器,可以通过将其发送为真值来重置该值。 如果重置了生成器,则它将从"string"[0:2] == "st"的开头重新开始产生。

然后,它将连续的"string"[0:2] == "st"值与生成器的收益进行比较,如果它们不匹配,则重置生成器。

当生成器的值用完时,即未重置就到达"string"[0:2] == "st"的末尾,这意味着我们已经找到匹配项。

由于它适用于任何序列,因此您甚至可以在字符串上使用它,在这种情况下,它的行为类似于"string"[0:2] == "st",除了它返回False而不是-1。

进一步说明:我认为,返回的元组的第二个值通常应与Python标准保持较高。 即"string"[0:2] == "st"。但是规范中另有说明,因此就是这样。

这取决于它是要用作通用例程还是要实现某些特定目标。 在后一种情况下,最好实现一个通用例程,然后将其包装在一个函数中,该函数会扭曲返回值以适合规范。

def reiterator(sub):

"""Yield elements of a sequence, resetting if sent ``True``."""

it = iter(sub)

while True:

if (yield it.next()):

it = iter(sub)

def find_in_sequence(sub, sequence):

"""Find a subsequence in a sequence.

>>> find_in_sequence([2, 1], [-1, 0, 1, 2])

False

>>> find_in_sequence([-1, 1, 2], [-1, 0, 1, 2])

False

>>> find_in_sequence([0, 1, 2], [-1, 0, 1, 2])

(1, 3)

>>> find_in_sequence("subsequence",

... "This sequence contains a subsequence.")

(25, 35)

>>> find_in_sequence("subsequence", "This one doesn't.")

False

"""

start = None

sub_items = reiterator(sub)

sub_item = sub_items.next()

for index, item in enumerate(sequence):

if item == sub_item:

if start is None: start = index

else:

start = None

try:

sub_item = sub_items.send(start is None)

except StopIteration:

# If the subsequence is depleted, we win!

return (start, index)

return False

intuited answered 2020-07-27T14:06:39Z

0 votes

我觉得这个很快

def issublist(subList, myList, start=0):

if not subList: return 0

lenList, lensubList = len(myList), len(subList)

try:

while lenList - start >= lensubList:

start = myList.index(subList[0], start)

for i in xrange(lensubList):

if myList[start+i] != subList[i]:

break

else:

return start, start + lensubList - 1

start += 1

return False

except:

return False

ChessMaster answered 2020-07-27T14:06:59Z

0 votes

大多数答案的问题在于,它们对于列表中的唯一项很有用。 如果项目不是唯一的,并且您仍然想知道是否有一个交集,则应该计算项目:

from collections import Counter as count

def listContains(l1, l2):

list1 = count(l1)

list2 = count(l2)

return list1&list2 == list1

print( listContains([1,1,2,5], [1,2,3,5,1,2,1]) ) # Returns True

print( listContains([1,1,2,8], [1,2,3,5,1,2,1]) ) # Returns False

您也可以使用''.join(list1&list2)返回交点

mafonya answered 2020-07-27T14:07:25Z

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值