有没有办法知道元素列表是否在更大的列表中而不使用'in'关键字?

时间:2009-10-29 21:23:55

标签: python

我想这样做。我有两个python列表,一个比另一个更大,我想知道是否有一种方法可以检查较小列表中的元素是否以完全相同的顺序位于大列表中,例如:

small_list = [4,2,5]
big_list = [1,2,5,7,2,4,2,5,67,8,5,13,45]

我尝试使用 in 关键字,但它没有用:'(

10 个答案:

答案 0 :(得分:7)

def in_list(small, big):
    l_sml = len(small)
    l_big = len(big)
    return any((big[i:i+l_sml]==small for i in xrange(l_big-l_sml+1)))

print in_list([4,2,1], [1,2,3,4,2,1,0,5]) # True
print in_list([1,2,3], [1,2,4])           # False

答案 1 :(得分:4)

嗯,也许这太过分了,但你可以使用difflib的SequenceMatcher类:

from difflib import SequenceMatcher 
small_list = [4,2,5]
big_list = [1,2,5,7,2,4,2,5,67,8,5,13,45]
print SequenceMatcher(None, small_list, big_list).get_matching_blocks()

difflib documentation

答案 2 :(得分:3)

相当非优化,简单地演示了一般策略:

tuple(small_list) in zip(big_list[:], big_list[1:], big_list[2:])

时髦的拉链做到了这一点:

>>> zip(big_list[:], big_list[1:], big_list[2:])
[(1, 2, 5), (2, 5, 7), (5, 7, 2), (7, 2, 4), (2, 4, 2), (4, 2, 5), (2, 5, 67), (5, 67, 8), (67, 8, 5), (8, 5, 13), (5, 13, 45)]

更优化的版本:

from itertools import izip, islice
tuple(small_list) in izip(big_list, islice(big_list, 1, None), islice(big_list, 2, None))

处理任何大小的small_list长度:

from itertools import izip, islice
tuple(small_list) in izip(*(islice(big_list, i, None) for i in xrange(len(small_list))))

答案 3 :(得分:2)

这个问题比看起来更棘手。除非我弄错了,否则这是longest common substring problem的特例。

对于一般情况(任意大的列表),我会使用某种finite state automaton,类似于正则表达式。我相信结果可以在O(mn)时间内计算。

答案 4 :(得分:2)

那是因为small_list in big_list检查big_list中的元素是否等于small_list。你想要做的是看一块big_list是否与small_list相同。

def isSubList(slice, L):
    n = len(slice)
    for i in range(0, len(L) - n):
        if slice == L[i:i+n]:
            return True
    return False

isSubList(small_list, big_list)

答案 5 :(得分:1)

编辑:在这里留下答案,但我没有注意到要求它们处于相同的顺序。这不符合要求

快速而肮脏的回答。基于Python - Intersection of two lists

的答案
small_list == filter( lambda x: x in big_list, small_list)

答案 6 :(得分:1)

如果您知道数字的合理范围,则可以将它们转换为Python类型,其'in'运算符会自动执行此操作。我知道的两个是strunicode

然后你问字符串是否较小的字符串,这是一个子字符串比较:

>>> small_list = [4,2,5]
>>> big_list = [1,2,5,7,2,4,2,5,67,8,5,13,45]
>>>
>>> def encode(lst):
      return u"".join(unichr(c) for c in lst)

>>> encode(small_list) in encode(big_list)
True

(如果所有数字都在str,您可以“编码”到0 <= x <= 255,如果所有数字都在unicode中,您可以“编码”到0 <= x <= sys.maxunicode

答案 7 :(得分:0)

没有内置的操作员进行特定的比较。我建议列表理解或快速循环。

答案 8 :(得分:0)

你可以使用套装

from sets import Set
small_set = set(small_list)
big_set = set(big_list)
small_set <= big_set

&lt; =是子集运算符

答案 9 :(得分:0)

如果您想使用“in”关键字来执行您想要的操作,可以使用此处答案中提到的解决方案之一覆盖包含

class mylist(list):
    def __contains__(self, lst):
        return ':'.join(map(str, lst)) in ':'.join(map(str, self))

small_list = mylist([4,2,5])
big_list = mylist([1,2,5,7,2,4,2,5,67,8,5,13,45])

print small_list in big_list

编辑:解答杰弗里的评论。