索引的pythonic格式 [英] pythonic format for indices
问题描述
我正在使用字符串格式来有效地表示一组索引。
例如1-3,6,8-10,16将产生[1,2,3,6,8,9,10,16]
I am after a string format to efficiently represent a set of indices. For example "1-3,6,8-10,16" would produce [1,2,3,6,8,9,10,16]
理想情况下,我也能够代表无限的序列。
Ideally I would also be able to represent infinite sequences.
是否有现成的标准方法?还是一个好的图书馆?或者您可以提出自己的格式吗?
Is there an existing standard way of doing this? Or a good library? Or can you propose your own format?
谢谢!
编辑:哇! - 感谢所有考虑周全的回复。我同意我应该使用':'代替。关于无限列表的任何想法?我想用1 ..代表所有正数。
Wow! - thanks for all the well considered responses. I agree I should use ':' instead. Any ideas about infinite lists? I was thinking of using "1.." to represent all positive numbers.
用例是购物车。对于某些产品,我需要将产品销售限制为X的倍数,对于其他产品,则需要任何正数。所以我在数据库中用字符串格式表示。
The use case is for a shopping cart. For some products I need to restrict product sales to multiples of X, for others any positive number. So I am after a string format to represent this in the database.
推荐答案
如果你是Pythonic,我想 1:3,6,8:10,16
将是更好的选择,因为 x:y
是标准符号对于索引范围和语法允许您在对象上使用此表示法。请注意,电话
If you're into something Pythonic, I think 1:3,6,8:10,16
would be a better choice, as x:y
is a standard notation for index range and the syntax allows you to use this notation on objects. Note that the call
z[1:3,6,8:10,16]
被翻译成
z.__getitem__((slice(1, 3, None), 6, slice(8, 10, None), 16))
即使这是 TypeError
如果 z
是一个内置容器,你也是免费的创建将返回合理内容的类,例如作为NumPy的数组。
Even though this is a TypeError
if z
is a built-in container, you're free to create the class that will return something reasonable, e.g. as NumPy's arrays.
您可能还会按惯例说明 5:
和:5
表示无限的索引范围(由于Python没有带有负或无限大正索引的内置类型,因此有点拉伸。)
You might also say that by convention 5:
and :5
represent infinite index ranges (this is a bit stretched as Python has no built-in types with negative or infinitely large positive indexes).
和这是解析器(一个漂亮的单行,受到切片(16,无,无)
下面描述的毛刺):
And here's the parser (a beautiful one-liner that suffers from slice(16, None, None)
glitch described below):
def parse(s):
return [slice(*map(int, x.split(':'))) for x in s.split(',')]
然而,有一个陷阱: 8:10
按定义仅包括索引8和9 - 没有上限。如果这对你的目的来说是不可接受的,你当然需要一种不同的格式,并且 1-3,6,8-10,16
看起来对我很好。然后解析器将
There's one pitfall, however: 8:10
by definition includes only indices 8 and 9 -- without upper bound. If that's unacceptable for your purposes, you certainly need a different format and 1-3,6,8-10,16
looks good to me. The parser then would be
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(',')]
更新:这里是组合格式的完整解析器:
Update: here's the full parser for a combined format:
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将其识别为内置常量省略号,因此您可以调用 z [...]
如果你愿意,但我认为 1,...,3,6,8,...,10,16
不太可读。
Yet another alternative is to use ...
(which Python recognizes as the built-in constant Ellipsis so you can call z[...]
if you want) but I think 1,...,3,6, 8,...,10,16
is less readable.
这篇关于索引的pythonic格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!