有很多方法可以解决这个问题,但这里有两种方法可以满足您的需要:
这取决于您要如何评估和找到您正在寻找的模式。从您的问题来看,尚不清楚您的数据是否来自 4 个条目的预格式化“数据包”,您在其中寻找“2 绿 2 红”或“2 红 2 绿”的识别模式,所以我将假设第一个示例不是这种情况。在第二个示例中,我将说明如果该假设为为真,如何处理。
示例 1:遍历颜色列表并在最后 4 个条目(包括当前迭代)中找到您要查找的模式。
def evaluate_by_iteration(_colors):
# -- skip the first three entries
for i in range(4, len(_colors)):
# -- get the preceding three elements and the current one.
# -- note the "i+1" here, this is how list slicing works
first, second, third, fourth = _colors[i-3: i+1]
if (first == second == 'GREEN') and (third == fourth == 'RED'):
print('[iterator] PLEASE SELL')
elif (first == second == 'RED') and (third == fourth == 'GREEN'):
print('[iterator] PLEASE BUY')
示例 2:将列表分块为大小为 4 的数据包,并检查每个数据包是否符合模式。 仅在预计数据会以这种方式分块时才这样做! (再次,从您的问题中不清楚)
from itertools import izip_longest
def evaluate_by_chunks(_colors):
chunked_colors = izip_longest(*[iter(_colors)] * 4, fillvalue=None)
for chunk in list(chunked_colors):
first, second, third, fourth = chunk
if (first == second == 'GREEN') and (third == fourth == 'RED'):
print('[chunker] PLEASE SELL')
if (first == second == 'RED') and (third == fourth == 'GREEN'):
print('[chunker] PLEASE BUY')
为什么要使用第二种方法而不是第一种方法?
这取决于您希望如何评估您的数据。取以下数据集:
colors = ['RED', 'GREEN', 'RED', 'RED', 'GREEN', 'GREEN', 'RED', 'RED']
print('-------------')
print('EVALUATE BY ITERATION')
evaluate_by_iteration(colors)
print(' ')
print('-------------')
print('EVALUATE BY CHUNKS')
evaluate_by_chunks(colors)
print(' ')
这将打印:
-------------
EVALUATE BY ITERATION
[iterator] PLEASE BUY
[iterator] PLEASE SELL
-------------
EVALUATE BY CHUNKS
[chunker] PLEASE SELL
请注意“迭代求值”有两个匹配项,因为我们每次只将搜索索引加一。
现在,根据您的需要,其中任何一个都可能是正确的;使用基于迭代器的方法,您将找到您要查找的模式的每个实例,包括重叠的模式,例如“GREEN GREEN RED RED GREEN GREEN”模式。
使用基于块的方法,您可以确保永远不会评估重叠的模式,但前提是您的数据被很好地组织在大小为 4 的数据包中。
最后一种方法采用迭代器方法,但确保没有项目被评估两次;在这个例子中,我们重写了基于迭代的求值方法,但是我们没有回头看,而是向前看。这允许我们在找到模式匹配时手动增加“index”变量,确保我们在匹配时跳过模式。
这允许数据相对非结构化,同时确保您不会评估重叠模式。
def evaluate_by_iteration_looking_forward(_colors):
# -- skip the first three entries
counter = 0
for i in range(0, len(_colors) - 3):
if counter > len(_colors) - 3:
break
first, second, third, fourth = _colors[counter: counter + 4]
if (first == second == 'GREEN') and (third == fourth == 'RED'):
print('[iterator] PLEASE SELL')
counter += 4
continue
elif (first == second == 'RED') and (third == fourth == 'GREEN'):
print('[iterator] PLEASE BUY')
counter += 4
continue
counter += 1
为了测试这一点,我们运行以下代码:
print('-------------')
print('EVALUATE BY ITERATION')
evaluate_by_iteration(colors)
print(' ')
print('-------------')
print('EVALUATE BY CHUNKS')
evaluate_by_chunks(colors)
print(' ')
print('-------------')
print('EVALUATE BY ITERATION LOOKING FORWARD')
evaluate_by_iteration_looking_forward(colors)
哪些打印:
-------------
EVALUATE BY ITERATION
[iterator] PLEASE BUY
[iterator] PLEASE SELL
-------------
EVALUATE BY CHUNKS
[chunker] PLEASE SELL
-------------
EVALUATE BY ITERATION LOOKING FORWARD
[iterator] PLEASE BUY
如您所见,我们的前瞻性评估器仅匹配第一个模式,然后跳过 head,确保它不会与之前已经评估过的元素再次匹配。