预计算len(范围(开始,停止,步骤))

时间:2013-02-07 15:31:51

标签: python indexing slice

如何在实际调用之前计算调用range(start, stop, step)时产生的元素数量。

上下文是我正在将切片索引实现为对象

def __init__(self, impl_object):
   self.impl=impl_object # the object that actually holds (or generates) an array of values
def __getitem__(self, key):
    if isinstance(key, slice):
         (start,stop,step)=key.indices( self.impl.numValues() )
         # It would be nice to know how many items I'm dealing with
         # here
    ...snip...

我已经说服了step>0 len(range(start,stop,step))==(start-stop+step-1)/step

但我不知道如何将这一点推广为消极步骤。

编辑:我要求(强烈希望)解决方案花费O(1)时间。

3 个答案:

答案 0 :(得分:4)

最简单的方法是

len(xrange(start, stop, step))

xrange.__len__计算yield元素的数量,而不在内存中构建范围。

答案 1 :(得分:2)

如果您的startstopstepthe implementation-specific limitations for xrange一致(例如CPython 2. x 要求他们' “短”Python整数'),您可以通过调用获得range(start, stop, step)将包含的值的数量:

len(xrange(start, stop, step))

在幕后,xrange()调用会返回xrange object

  

XRange对象的行为非常少:它们只支持索引,   迭代和len()函数。

len()调用是O(1),因为xrange类型使用基于传递的参数的计算实现__len__方法,并且len()发现传递给它的对象实现__len__,并调用它来获取长度。

如果您的startstopstep可能不适用于xrange(),则此处为a blog post with an xrange implementation的功能a Hacker News discussion {3}}):

def len_range(start, stop, step):
    return max(0, (stop - start) // step + bool((stop - start) % step))

答案 2 :(得分:0)

尝试使用abs(步骤)而不是步骤。