如果您喜欢Pythonic,我认为1:3,6,8:10,16
这是一个更好的选择,x:y
索引范围的标准符号也是如此,并且语法允许您在对象上使用此符号。注意通话
z[1:3,6,8:10,16]
被翻译成
z.__getitem__((slice(1, 3, None), 6, slice(8, 10, None), 16))
即使这是一个TypeError
ifz
内置容器,您也可以自由创建将返回合理值的类,例如NumPy的数组。
您可能还会说,按照惯例5:
,它:5
表示无限索引范围(由于Python没有带有负数或无限大的正索引的内置类型,因此有点过分了)。
这是解析器(一个很漂亮的单线代码,有slice(16, None, None)
如下所述的毛刺):
def parse(s):
return [slice(*map(int, x.split(':'))) for x in s.split(',')]
但是有一个陷阱:8:10
根据定义,它仅包含索引8和9-没有上限。如果这对于您的目的是不可接受的,那么您当然需要其他格式,并且1-3,6,8-10,16
对我来说不错。然后解析器将是
def myslice(start, stop=None, step=None):
return slice(start, (stop if stop is not None else start) + 1, step)
def parse(s):
return [myslice(*map(int, x.split('-'))) for x in s.split(',')]
这是组合格式的完整解析器:
from sys import maxsize as INF
def indices(s: 'string with indices list') -> 'indices generator':
for x in s.split(','):
splitter = ':' if (':' in x) or (x[0] == '-') else '-'
ix = x.split(splitter)
start = int(ix[0]) if ix[0] is not '' else -INF
if len(ix) == 1:
stop = start + 1
else:
stop = int(ix[1]) if ix[1] is not '' else INF
step = int(ix[2]) if len(ix) > 2 else 1
for y in range(start, stop + (splitter == '-'), step):
yield y
这也处理负数,所以
print(list(indices('-5, 1:3, 6, 8:15:2, 20-25, 18')))
版画
[-5, 1, 2, 6, 7, 8, 10, 12, 14, 20, 21, 22, 23, 24, 25, 18, 19]
还有一种替代方法是使用...
(Python将其识别为内置常数Ellipsis,因此您可以z[...]
根据需要调用它),但我认为1,...,3,6,8,...,10,16
它的可读性较差。