当在Python中实现可以使用标准Python语法切片的类(即负索引,步进等)时,有时将切片转换为一个理智的前向切片"确定切片的元素。如何以简洁/优雅的形式编写这样的功能?
使用"理智,前向切片"我的意思是一个切片,它相当于初始切片,因为结果元素是相同的,但是有一个正步骤,没有负指数,也没有大于对象长度的索引。
示例(假设数组长度为10):
slice(None, 4,None) -> slice( 0, 4, 1)
slice( -7, 12, 1) -> slice( 3,10, 1)
slice(None,None, -1) -> slice( 0,10, 1)
slice( 7, 3, -2) -> slice( 5, 8, 2)
slice( 9, 1, -3) -> slice( 3,10, 3)
编写执行这种转换的函数并不是非常困难,但我无法简洁地编写它。特别是在转换"向后切片时确定起始索引"进入一个等同的"前向切片"似乎很麻烦。
工作示例:
def to_sane_slice(s, N):
step = s.step if s.step is not None else 1
if step == 0:
ValueError('Slice step cannot be 0!')
# get first index
first = s.start
if first is None:
first = 0 if step > 0 else N-1
elif first < 0:
first = N+first
if first < 0:
if step < 0:
return slice(0,0,1)
first = 0
elif first >= N:
if step > 0:
return slice(0,0,1)
first = N-1
# get stop index
stop = s.stop
if stop is None:
stop = N if step > 0 else -1
elif stop < 0:
stop = max(-1, N+stop)
# check for etmpy slices
if (stop-first)*step <= 0:
return slice(0,0,1)
if step > 0:
return slice(first, min(stop,N), step)
elif step == -1:
return slice(stop+1, first+1, -step)
else:
# calculate the new start -- does not have to be next to old stop, since
# the stepping might lead elsewhere
step = -step
dist = first - max(stop,-1)
last = first - dist / step * step
if dist % step == 0:
last += step
return slice(last, first+1, step)
。
。
。
编辑(最终功能):
使用slice.indices()
@doublep向我指出它变为:
def to_sane_slice(s, N):
# get rid of None's, overly large indices, and negative indices (except -1 for
# backward slices that go down to first element)
start, stop, step = s.indices(N)
# get number of steps & remaining
n, r = divmod(stop - start, step)
if n < 0 or (n==0 and r==0):
return slice(0,0,1)
if r != 0: # its a "stop" index, not an last index
n += 1
if step < 0:
start, stop, step = start+(n-1)*step, start-step, -step
else: # step > 0, step == 0 is not allowed
stop = start+n*step
stop = min(stop, N)
return slice(start, stop, step)
答案 0 :(得分:3)
使用.blink
方法。
S.indices(len) - &gt; (开始,停止,跨步)
假设长度为len的序列,计算起始和停止索引,以及由S描述的扩展切片的步长。超出边界索引的裁剪方式与正常切片的处理一致。