hoj*_*oju 6 python indexing set sequence
我正在使用字符串格式来有效地表示一组索引.例如"1-3,6,8-10,16"会产生[1,2,3,6,8,9,10,16]
理想情况下,我也能够代表无限的序列.
是否有现成的标准方法?还是一个好的图书馆?或者你可以提出自己的格式吗?
谢谢!
编辑:哇! - 感谢所有考虑周全的回复.我同意我应该使用':'代替.关于无限列表的任何想法?我想用"1 .."代表所有正数.
用例是购物车.对于某些产品,我需要将产品销售限制为X的倍数,对于其他产品,我要将其限制为正数.所以我追求一种字符串格式来代表数据库.
你不需要一个字符串,这很简单:
from types import SliceType
class sequence(object):
def __getitem__(self, item):
for a in item:
if isinstance(a, SliceType):
i = a.start
step = a.step if a.step else 1
while True:
if a.stop and i > a.stop:
break
yield i
i += step
else:
yield a
print list(sequence()[1:3,6,8:10,16])
Run Code Online (Sandbox Code Playgroud)
输出:
[1, 2, 3, 6, 8, 9, 10, 16]
Run Code Online (Sandbox Code Playgroud)
我正在使用Python切片类型的功能来表达序列范围.我也使用生成器来提高内存效率.
请注意,我在切片停止处添加1,否则范围将不同,因为切片中的停止不包括在内.
它支持以下步骤:
>>> list(sequence()[1:3,6,8:20:2])
[1, 2, 3, 6, 8, 10, 12, 14, 16, 18, 20]
Run Code Online (Sandbox Code Playgroud)
无限的序列:
sequence()[1:3,6,8:]
1, 2, 3, 6, 8, 9, 10, ...
Run Code Online (Sandbox Code Playgroud)
如果你必须给它一个字符串,那么你可以组合@ilya n.使用此解决方案解析器.我会延长@ilya n.解析器以支持索引和范围:
def parser(input):
ranges = [a.split('-') for a in input.split(',')]
return [slice(*map(int, a)) if len(a) > 1 else int(a[0]) for a in ranges]
Run Code Online (Sandbox Code Playgroud)
现在您可以像这样使用它:
>>> print list(sequence()[parser('1-3,6,8-10,16')])
[1, 2, 3, 6, 8, 9, 10, 16]
Run Code Online (Sandbox Code Playgroud)
如果您喜欢Pythonic,我认为这1:3,6,8:10,16
将是一个更好的选择,因为x:y
索引范围的标准表示法和语法允许您在对象上使用此表示法。请注意,调用
z[1:3,6,8:10,16]
Run Code Online (Sandbox Code Playgroud)
被翻译成
z.__getitem__((slice(1, 3, None), 6, slice(8, 10, None), 16))
Run Code Online (Sandbox Code Playgroud)
即使这是一个TypeError
ifz
是内置容器,您也可以自由创建将返回合理内容的类,例如 NumPy 的数组。
您也可能会说,按照惯例5:
,:5
表示无限索引范围(这有点夸张,因为 Python 没有带有负索引或无限大正索引的内置类型)。
这是解析器(一个漂亮的单行代码,但存在slice(16, None, None)
如下所述的故障):
def parse(s):
return [slice(*map(int, x.split(':'))) for x in s.split(',')]
Run Code Online (Sandbox Code Playgroud)
然而,有一个陷阱: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(',')]
Run Code Online (Sandbox Code Playgroud)
更新:这是组合格式的完整解析器:
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
Run Code Online (Sandbox Code Playgroud)
这也处理负数,所以
print(list(indices('-5, 1:3, 6, 8:15:2, 20-25, 18')))
Run Code Online (Sandbox Code Playgroud)
印刷
[-5, 1, 2, 6, 7, 8, 10, 12, 14, 20, 21, 22, 23, 24, 25, 18, 19]
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用...
(Python 将其识别为内置常量省略号,因此您可以z[...]
根据需要调用),但我认为1,...,3,6, 8,...,10,16
可读性较差。
归档时间: |
|
查看次数: |
270 次 |
最近记录: |