如果我有这个:
a='abcdefghij'
b='de'
然后在a:
中找到bb in a => True
有没有办法用列表做类似的事情? 像这样:
a=list('abcdefghij')
b=list('de')
b in a => False
“假”结果是可以理解的 - 因为它正确地寻找元素'de',而不是(我碰巧想要它做什么)'d'后跟'e'
这是有效的,我知道:
a=['a', 'b', 'c', ['d', 'e'], 'f', 'g', 'h']
b=list('de')
b in a => True
我可以处理数据以获得我想要的东西 - 但是有一个简短的Pythonic方法吗?
澄清一下:我需要在这里保留排序(b = ['e','d'],应该返回False)。
如果它有帮助,我所拥有的是一个列表列表:这些列表代表有向图中从节点1到节点-x的所有可能路径(受访节点列表):我想要“排除”任何更长路径中的公共路径。 (因此寻找所有不可缩短的“原子”路径,构成所有较长的路径)。
答案 0 :(得分:11)
我怀疑有更多的pythonic方式,但至少它完成了工作:
l=list('abcdefgh')
pat=list('de')
print pat in l # Returns False
print any(l[i:i+len(pat)]==pat for i in xrange(len(l)-len(pat)+1))
答案 1 :(得分:7)
我认为这会更快 - 它使用C实现list.index
来搜索第一个元素,并从那里开始。
def find_sublist(sub, bigger):
if not bigger:
return -1
if not sub:
return 0
first, rest = sub[0], sub[1:]
pos = 0
try:
while True:
pos = bigger.index(first, pos) + 1
if not rest or bigger[pos:pos+len(rest)] == rest:
return pos
except ValueError:
return -1
data = list('abcdfghdesdkflksdkeeddefaksda')
print find_sublist(list('def'), data)
请注意,这会返回列表中子列表的位置,而不仅仅是True
或False
。如果您只想要一个bool
,可以使用它:
def is_sublist(sub, bigger):
return find_sublist(sub, bigger) >= 0
答案 2 :(得分:6)
不知道这是非常pythonic,但我会这样做:
def is_sublist(a, b):
if not a: return True
if not b: return False
return b[:len(a)] == a or is_sublist(a, b[1:])
此discussion中提供了更短的解决方案,但它遇到与set
解决方案相同的问题 - 它不考虑元素的顺序。
更新:
受MAK的启发,我介绍了更简洁明了的代码版本。
更新: 由于列表中的列表复制,此方法存在性能问题。此外,由于它是递归的,您可能会遇到长列表的递归限制。要消除复制,您可以使用Numpy creates views, not copies个切片。如果遇到性能或递归限制问题,则应使用不带递归的解决方案。
答案 3 :(得分:3)
我计划了接受的解决方案,我早期的解决方案以及带索引的新解决方案。具有指数的人显然是最好的。
编辑:我计划了nosklo的解决方案,它甚至比我想出的要好得多。 :)def is_sublist_index(a, b):
if not a:
return True
index = 0
for elem in b:
if elem == a[index]:
index += 1
if index == len(a):
return True
elif elem == a[0]:
index = 1
else:
index = 0
return False
def is_sublist(a, b):
return str(a)[1:-1] in str(b)[1:-1]
def is_sublist_copylist(a, b):
if a == []: return True
if b == []: return False
return b[:len(a)] == a or is_sublist_copylist(a, b[1:])
from timeit import Timer
print Timer('is_sublist([99999], range(100000))', setup='from __main__ import is_sublist').timeit(number=100)
print Timer('is_sublist_copylist([99999], range(100000))', setup='from __main__ import is_sublist_copylist').timeit(number=100)
print Timer('is_sublist_index([99999], range(100000))', setup='from __main__ import is_sublist_index').timeit(number=100)
print Timer('sublist_nosklo([99999], range(100000))', setup='from __main__ import sublist_nosklo').timeit(number=100)
以秒为单位的输出:
4.51677298546
4.5824368
1.87861895561
0.357429027557
答案 4 :(得分:2)
因此,如果您不关心子集出现的顺序,您可以这样做:
a=list('abcdefghij')
b=list('de')
set(b).issubset(set(a))
True
在您澄清之后进行编辑:如果您需要保留订单,并且列表确实是您问题中的字符,则可以使用:
''.join(a).find(''.join(b)) > 0
答案 5 :(得分:2)
这应该适用于任何列表,保留订单。 正在检查 b 是 a
的子列表def is_sublist(b,a):
if len(b) > len(a):
return False
if a == b:
return True
i = 0
while i <= len(a) - len(b):
if a[i] == b[0]:
flag = True
j = 1
while i+j < len(a) and j < len(b):
if a[i+j] != b[j]:
flag = False
j += 1
if flag:
return True
i += 1
return False
答案 6 :(得分:1)
>>>''.join(b) in ''.join(a)
True
答案 7 :(得分:0)
不确定您的应用程序有多复杂,但对于列表中的模式匹配,pyparsing非常智能且易于使用。
答案 8 :(得分:-1)
使用列表的字符串表示并删除方括号。 :)
def is_sublist(a, b):
return str(a)[1:-1] in str(b)
编辑:对,有误报......例如is_sublist([1], [11])
。蹩脚的回答。 :)