索引的pythonic格式 [英] pythonic format for indices

查看:143
本文介绍了索引的pythonic格式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用字符串格式来有效地表示一组索引。
例如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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆