我有一个包含大量bool
值的列表,我希望得到这种模式:True, True, False, True, True
。为此,我认为我需要在处理前一个元素时获取循环中的下一个元素。我该怎么办?
奖金问题:有没有办法增加i += 1
之外的列表中元素的位置?
答案 0 :(得分:2)
我会捅一下:
subset = [True, True, False, True, True]
main = [False, True, False, True, True, True, False, True, True, False, True, False, True]
for i, j in enumerate(xrange(len(subset), len(main) + 1)):
if main[i:j] == subset:
print subset, 'is at', i
break
else:
print 'not found'
注意:这有点粗暴,但一次性还可以......否则,看看尝试......
答案 1 :(得分:1)
l = len(some_list) - 3
for i, thing in enumerate(some_list):
if i == l: break
if thing and some_list[i+1] and not some_list[i+2] and some_list[i+3]:
bingo(i)
另一个未经测试的尝试:
needle = [True, True, False, True, True]
needle_len = len(needle)
for i in range(len(stack)-needle_len+1):
if needle == stack[i:i+needle_len]:
bingo(i)
答案 2 :(得分:1)
如果我正确理解了这个问题,那么你要做的事情与str.find
完全相同,但是要查找列表中的子列表而不是字符串中的子字符串。
如果是这样的话:
def findSubList(l, sub):
return (''.join('T' if x else 'F' for x in l)
.find(''.join('T' if x else 'F' for x in sub)))
这看似hacky,但它有意义:你想在列表中找到一个子列表,两者都可以简单地转换为字符串,并且已经有一个内置函数来查找字符串中的子字符串,那么为什么不使用呢?
它可能会变得太慢,但实际上,对它进行编码是如此之快以至于值得测试它以确定它是否太慢以至于您的目的。 (即使它太慢,它可能是转换为字符串的部分很慢,并且首先使用字符串而不是bool列表可能是合理的,或者在进行200次搜索之前在开始时转换一次或者其他什么。)
如果这不可避免地太慢,我接下来要做的就是查看str.find
的实现并将其转换为通用序列find。你有Python的源代码,所以这不应该太难。但是,str.find
可能在C中,这可能会让端口感到痛苦。在这种情况下,您仍然可能希望在线搜索纯Python str.find
...但我们假设您没有找到它。
下一步是查看PyPI上是否有序列查找模块。
如果没有,有一些众所周知的算法要么易于实现,要么在ActiveState甚至Wikipedia等地方实现自由实现。请参阅维基百科的String searching algorithm以获取列表和一些比较。 (性能特征取决于您没有给我们的因素 - 您需要进行多少次搜索;主要,子集或两者都有所不同;等等,这意味着没有更多信息,没有人能猜出哪一个最好。)
即使是标准的字符串搜索算法也可能不够快,并且利用您搜索单个位而不是8位字符的事实可以获得很大的效率提升。 (如果模式是固定的,您甚至应该能够将搜索描述为有限状态机,并将其转换为硬编码,可证明最佳的实现......)
所以,你可能必须自己设计一些东西。但是你不太可能这样做,如果可能的话,我会避免这样做。每当你遇到一个明显常见的问题时,值得假设这是一个已解决的问题并寻找解决方案,而不是试图从第一原则来解决它。
答案 3 :(得分:0)
相当高效,使用滑动窗口方法,应该在线性时间运行。
def find_x_in_y(subset, main):
""" Returns a list of the indexes of the first value of matches. """
results = []
for i in xrange(len(main)):
if main[i:i+5] == subset:
results.append(i)
return results
# values borrowed from @JonClements
subset = [True, True, False, True, True]
main = [False, True, False, True, True, True, False, True, True, False, True, False, True]
>>> find_x_in_y(subset, main)
... [4]
@abarnert很好,这是实际非常有效的方法。
非常高效,将整个bool列表转换为bitarray并运行本机搜索方法。
from bitarray import bitarray
def find_x_in_y(subset, main):
subarray = bitarray(subset)
mainarray = bitarray(main)
return [int(i) for i in mainarray.itersearch(subarray)]
timeit
结果:
Length of main: 10 100 1000 10000 100000 1000000
returning _all_ matches:
# number of matches 1 10 100 1000 10000 100000
# sliding window approach (0.00059, 0.00502, 0.04194, 0.26211, 2.55554, 26.21962)
# bitarray approach (0.00028, 0.00072, 0.00484, 0.02926, 0.2822, 2.93676)
returning first match:
# sliding window approach (0.00034, 0.00034, 0.00034, 0.00021, 0.00026, 0.00059)
# bitarray approach (0.00017, 0.00017, 0.00016, 0.00011, 0.00014, 0.00049)
# joined string approach (0.00134, 0.00721, 0.06244, 0.39224, 4.21628, 39.63207)