【问题标题】:Parsing an optional list of ranges解析可选范围列表
【发布时间】:2016-12-28 01:13:20
【问题描述】:

我的脚本需要一个选项后跟一个页面列表,指定为逗号分隔的范围列表,并处理扩展的页面列表。所以,例如,

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 东西比较陌生,想知道是否有更好的方法来做到这一点?

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

【问题讨论】:

  • 我同意,这些都不是一个好的副本。他们没有阅读你的问题。但如果这种处理有效,这是一个很好的解决方案。自定义 type 是在 argparse 中执行此操作的唯一方法。
  • 只要您的用户不想用空格分隔数字,这是最好的解决方案。

标签: python argparse


【解决方案1】:

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

给定:

>>> 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]

希望这是显而易见的。给定列表[2, 2],我们调用range(2, 3),得到[2]。应用到之前操作的所有结果中,我们得到了我们之前看到的结果:

[[2], [4, 5, 6], [9], [10, 11, 12, 13]]

现在你的问题是“我如何展平列表”,一个解决方案(来自here)是:

>>> import itertools
>>> list(itertools.chain.from_iterable(result))
[2, 4, 5, 6, 9, 10, 11, 12, 13]

【讨论】:

  • 我猜您在第一行代码中的意思是 r 而不是 range。此外,您的解决方案(以及我的解决方案)存在用户可能指定愚蠢范围(重复、重叠等)的问题。我想最简单的处理方法是将列表转换为集合,然后再转换回列表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-23
  • 1970-01-01
  • 1970-01-01
  • 2010-09-09
  • 1970-01-01
  • 2012-04-20
相关资源
最近更新 更多