一种比完全构造排序列表更有效的方法(并且应该适用于任意可迭代类型,包含允许大于比较的任何数据类型):
def len_ascending_run_from_start(seq):
vals = enumerate(seq)
try:
c,x = 1, vals.next()[1]
except StopIteration:
raise ValueError("Sequence is empty!")
for i, cur_x in vals:
if cur_x < x:
break
c,x = c+1, cur_x
return c
例如:
In [44]: len_ascending_run_from_start([datetime.date(2012,1,4), datetime.date(2012,1,3), datetime.date(2012,1,5)])
Out[44]: 1
In [45]: len_ascending_run_from_start([datetime.date(2012,1,4), datetime.date(2012,1,6), datetime.date(2012,1,5)])
Out[45]: 2
In [46]: len_ascending_run_from_start([datetime.date(2012,1,4), datetime.date(2012,1,6), datetime.date(2012,1,7)])
Out[46]: 3
In [47]: len_ascending_run_from_start((1,2,3,4))
Out[47]: 4
In [48]: len_ascending_run_from_start((1,3,2,4))
Out[48]: 2
In [49]: len_ascending_run_from_start(set([1,3,2,4]))
Out[49]: 4
制作一个自动报告有关底层序列的统计信息的类也可能很有趣/有用len
(并保留结果的简单缓存,以避免重复计算)。
class AscendingRunFromStart(object):
def __init__(self, seq):
self.seq = seq
def __repr__(self):
return self.seq.__repr__()
__str__ = __repr__
def __len__(self):
if hasattr(self, "_len"):
return self._len
vals = enumerate(self.seq)
c,x = 1, vals.next()[1]
for i, cur_x in vals:
if cur_x < x:
break
c,x = c+1, cur_x
self._len = c
return self._len
例如:
In [76]: x = AscendingRunFromStart([1,3,2,4])
In [77]: x
Out[77]: [1, 3, 2, 4]
In [78]: len(x)
Out[78]: 2
一个好的扩展是使用描述符模式使seq
类的属性成为只读的,或者在调用len
时调用更新的计算set
。(留给读者练习……)