Python:如何在不创建范围的情况下计算范围的长度?

问题描述 投票:4回答:3

我需要计算一个范围的长度,但理想情况下不需要创建范围,(希望会更快并且使用更少的内存。这很重要,因为这个函数会被调用很多)。长度用于设置扩展切片。

现在我尝试过:

int_div = lambda n, d: (n + d // 2) // d

def range_len(start, stop, step):
    return int_div(stop - start, step)

但是在某些情况下,例如range_len(9,100,3),当正确的答案是31时它会给出30分。我觉得这应该很简单,我做错了什么?

python list python-2.7 slice
3个回答
6
投票

你可以使用这个公式:(end - start - 1) // step + 1

def calc_length(start, end, step):
    return (end - start - 1) // step + 1

for i in range(start, end):
    calculated = calc_length(start, i, step)
    empirical = len(range(start, i, step))

    assert calculated == empirical, "{} {}".format(calculated, empirical)

3
投票

在Python 2中,您可以使用xrange。在Python 3中,您可以使用range。在两者中,它们返回xrange / range对象而不是生成整个列表。

Python 2

return len(xrange(start, stop, step))

Python 3

return len(range(start, stop, step))

xrange帮助(在Python 2解释器类型help(xrange)):

class xrange(object)  
|  xrange([start,] stop[, step]) -> xrange object  
|  
|  Like range(), but instead of returning a list, returns an object that   
| generates the numbers in the range on demand.  For looping, this is  
|  slightly faster than range() and more memory efficient.

或者range帮助Python 3:

class range(object)  
 |  range(stop) -> range object  
 |  range(start, stop[, step]) -> range object  
 |  
 |  Return an object that produces a sequence of integers from start (inclusive)  
 |  to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.  
 |  start defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.  
 |  These are exactly the valid indices for a list of 4 elements.  
 |  When step is given, it specifies the increment (or decrement).

创建xrange / range对象比创建关联列表的长度更快,内存效率更高。

使用此方法计算0到1000000的范围使我的PC大约0.000004291534423828125秒,这比许多其他方法少。


1
投票

它给出30,因为当你希望它总是向上舍入时,你的整数除法会四舍五入到最接近的整数。我不知道它有多快,但我只是使用math.ceil和float division。

© www.soinside.com 2019 - 2024. All rights reserved.