Python 解析可选范围列表

Python 解析可选范围列表,python,argparse,Python,Argparse,我的脚本需要采用一个选项,后面是一个页面列表,指定为逗号分隔的范围列表,并处理扩展的页面列表。那么比如说, script.py -a 2,4-6,9,10-13 你应该得到这份名单 [2, 4, 5, 6, 9, 10, 11, 12, 13] 一起工作。目前我正在这样做: import argparse def getList(argument): ranges = list(argument.split(",")) newRange = [] for theRa

我的脚本需要采用一个选项,后面是一个页面列表,指定为逗号分隔的范围列表,并处理扩展的页面列表。那么比如说,

script.py -a 2,4-6,9,10-13
你应该得到这份名单

[2, 4, 5, 6, 9, 10, 11, 12, 13]
一起工作。目前我正在这样做:

import argparse

def getList(argument):
    ranges = list(argument.split(","))
    newRange = []
    for theRange in ranges:
        subRange = list(map(int, theRange.split("-")))
        if (len(subRange) > 1):
            newRange.extend(range(subRange[0], subRange[1] + 1))
        else:
            newRange.extend(subRange)
    newRange.sort()
    return newRange

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("-a", "--pages", type=getList, dest="pages", default=[], help="pages to process")
    args = parser.parse_args()
它是可以工作的,但我对Python还比较陌生,我想知道是否有更好的方法来实现它


编辑:我不明白为什么它被标记为重复问题。对于被标记为重复的问题,没有一个答案与我上面描述的完全相同。其思想不是处理一个简单的空格或逗号分隔参数列表,而是处理一个更复杂的范围列表,这些范围必须扩展。

这里有一个解决方案。这不一定是最好的。特别是,可能有一个更高性能的版本涉及链式迭代器,而不是嵌套迭代器

鉴于:

>>> range='2,4-6,9,10-13'
你可以这样做:

>>> result = [range(int(y[0]), int(y[1])+1) 
... for y in [(x.split('-') + [x])[:2]
... for x in r.split(',')]]
这让你:

>>> result
[[2], [4, 5, 6], [9], [10, 11, 12, 13]]
如果我们解开这些理解,最里面的一个会迭代:

>>> range.split(',')
['2', '4-6', '9', '10-13']
二是:

>>> result = range.split(',')
>>> [(x.split('-') + [x])[:2] for x in result]
[['2', '2'], ['4', '6'], ['9', '9'], ['10', '13']]
表达式
(x.split('-')+[x])[:2]
确保我们有一个两项列表,即使是单个数字,因此我们可以将其传递给
range
函数

最后,我们迭代该结果:

>>> [range(int(y[0]), int(y[1])+1) for y in <the result from the rpevious operation]
现在您的问题是“如何展平列表”,其中一个解决方案是:


我同意,这两个都不是好的复制品。他们没有读你的问题。但如果这种处理有效,这是一个很好的解决方案。自定义
类型
是在
argparse
中执行此操作的唯一方法。只要您的用户不想用空格分隔数字,这就是最佳解决方案。我猜您的意思是
r
而不是在第一行代码中使用
范围
。此外,您的解决方案(以及我的)存在一个问题,即用户可能会指定愚蠢的范围(重复、重叠等)。我想最简单的处理方法是将列表转换为集合,然后再转换回列表。
[[2], [4, 5, 6], [9], [10, 11, 12, 13]]
>>> import itertools
>>> list(itertools.chain.from_iterable(result))
[2, 4, 5, 6, 9, 10, 11, 12, 13]