通常情况下,我们需要处理一系列“块”,这些块从“原子”流中读取,每个块由可变数量的原子组成,并且程序无法知道是否接收到完整的块,直到读取下一个块的第一个原子(或者原子流耗尽)。
一个简单的执行此任务的算法如下:
因此,我的问题是:
这种一般类别的问题和/或上面显示的编程模式有没有名称?
本帖子的其余部分只是描述上述抽象内容的一些(相当现实的)示例。 (这些示例使用Python编写,尽管它们可以轻松翻译为任何命令式语言。)
第一个示例是生成输入字符串的运行长度编码的函数。 在这种情况下,“原子”是单个字符,“块”是最大的相同字符运行。 因此,程序在读取以下运行的第一个字符之前不知道已经到达了运行的结尾。
第二个例子是一个函数,它以读取FASTA格式文件的句柄作为参数,并解析其内容。在这种情况下,原子是文本行。每个块由一个特殊标记的第一行组成,称为“defline”(并以'>'作为其第一个字符),后跟包含核苷酸或蛋白质序列的可变数量的行。同样,只有在读取下一个块的第一个原子(即defline)之后,代码才能明确地检测到块的结束。
一个简单的执行此任务的算法如下:
LOOP FOREVER:
SET x TO NEXT_ATOM
IF DONE(x) OR START_OF_CHUNK(x):
IF NOT EMPTY(accum):
PROCESS(accum)
END
if DONE(x):
BREAK
END
RESET(accum)
END
ADD x TO accum
END
因此,我的问题是:
这种一般类别的问题和/或上面显示的编程模式有没有名称?
本帖子的其余部分只是描述上述抽象内容的一些(相当现实的)示例。 (这些示例使用Python编写,尽管它们可以轻松翻译为任何命令式语言。)
第一个示例是生成输入字符串的运行长度编码的函数。 在这种情况下,“原子”是单个字符,“块”是最大的相同字符运行。 因此,程序在读取以下运行的第一个字符之前不知道已经到达了运行的结尾。
def rle(s):
'''Compute the run-length encoding of s.'''
n = len(s)
ret = []
accum = 0
v = object() # unique sentinel; ensures first test against x succeeds
i = 0
while True:
x = s[i] if i < n else None
i += 1
if x is None or x != v:
if accum > 0:
ret.append((accum, v))
if x is None:
break
accum = 0
v = x
accum += 1
return ret
第二个例子是一个函数,它以读取FASTA格式文件的句柄作为参数,并解析其内容。在这种情况下,原子是文本行。每个块由一个特殊标记的第一行组成,称为“defline”(并以'>'作为其第一个字符),后跟包含核苷酸或蛋白质序列的可变数量的行。同样,只有在读取下一个块的第一个原子(即defline)之后,代码才能明确地检测到块的结束。
def read_fasta(fh):
'''Read the contents of a FASTA-formatted file.'''
ret = []
accum = []
while True:
x = fh.readline()
if x == '' or x.startswith('>'):
if accum:
ret.append((accum[0], ''.join(accum[1:])))
if x == '':
break
accum = []
accum.append(x.strip())
return ret