【问题标题】:Interpreting Number Ranges in Python在 Python 中解释数字范围
【发布时间】:2009-04-03 03:33:41
【问题描述】:

在 Pylons webapp 中,我需要获取一个字符串,例如“

关于如何做到这一点的任何建议?我是 Python 新手,我还没有找到任何可以帮助解决这类问题的东西。

列表将是:[1, 2, 3, 45, 46, 48, 49, 50, 51, 77]

【问题讨论】:

    标签: python numeric-ranges


    【解决方案1】:

    使用来自here的parseIntSet

    我也喜欢最后在 cmets 中的 pyparsing 实现。

    此处已修改 parseIntSet 以处理“

    #! /usr/local/bin/python
    import sys
    import os
    
    # return a set of selected values when a string in the form:
    # 1-4,6
    # would return:
    # 1,2,3,4,6
    # as expected...
    
    def parseIntSet(nputstr=""):
        selection = set()
        invalid = set()
        # tokens are comma seperated values
        tokens = [x.strip() for x in nputstr.split(',')]
        for i in tokens:
            if len(i) > 0:
                if i[:1] == "<":
                    i = "1-%s"%(i[1:])
            try:
                # typically tokens are plain old integers
                selection.add(int(i))
            except:
                # if not, then it might be a range
                try:
                    token = [int(k.strip()) for k in i.split('-')]
                    if len(token) > 1:
                        token.sort()
                        # we have items seperated by a dash
                        # try to build a valid range
                        first = token[0]
                        last = token[len(token)-1]
                        for x in range(first, last+1):
                            selection.add(x)
                except:
                    # not an int and not a range...
                    invalid.add(i)
        # Report invalid tokens before returning valid selection
        if len(invalid) > 0:
            print "Invalid set: " + str(invalid)
        return selection
    # end parseIntSet
    
    print 'Generate a list of selected items!'
    nputstr = raw_input('Enter a list of items: ')
    
    selection = parseIntSet(nputstr)
    print 'Your selection is: '
    print str(selection)
    

    这是示例运行的输出:

    $ python qq.py
    Generate a list of selected items!
    Enter a list of items: <3, 45, 46, 48-51, 77
    Your selection is:
    set([1, 2, 3, 45, 46, 77, 48, 49, 50, 51])
    

    【讨论】:

    • 没有“
    • 为什么要导入 sys 和 os,如果它们从未使用过?
    • @vartec,它们位于给定链接的原始代码中,我只更改了使“
    【解决方案2】:

    我创建了一个我觉得更具可读性的@vartec 解决方案版本:

    def _parse_range(numbers: str):
        for x in numbers.split(','):
            x = x.strip()
            if x.isdigit():
                yield int(x)
            elif x[0] == '<':
                yield from range(0, int(x[1:]))
            elif '-' in x:
                xr = x.split('-')
                yield from range(int(xr[0].strip()), int(xr[1].strip())+1)
            else:
                raise ValueError(f"Unknown range specified: {x}")
    

    在这个过程中,函数变成了一个生成器:)

    【讨论】:

      【解决方案3】:
      rng = "<3, 45, 46, 48-51, 77"
      ids = []
      for x in map(str.strip,rng.split(',')):
          if x.isdigit():
              ids.append(int(x))
              continue
          if x[0] == '<':
              ids.extend(range(1,int(x[1:])+1))
              continue
          if '-' in x:
              xr = map(str.strip,x.split('-'))
              ids.extend(range(int(xr[0]),int(xr[1])+1))
              continue
          else:
              raise Exception, 'unknown range type: "%s"'%x
      

      【讨论】:

        【解决方案4】:

        首先,您需要弄清楚您将接受哪种语法。您当前的示例中有三个:

        1. 单数:45、46

        2. 小于运算符

        3. 短跑范围:48-51

        之后,只需将字符串拆分为标记,并检查标记的格式即可。

        【讨论】:

          【解决方案5】:

          我最近也不得不为一个应用做类似的事情。

          如果您不需要具体的数字,而只是一种查看给定数字是否在范围内的方法,您可以考虑将其解析为 Python 表达式,您可以将其 eval 转换为 lambda。例如&lt;3, 5-10, 12 可以是func=(lambda x:x&lt;3 or (5 &lt;= x &lt;= 10) or x==12))。然后你可以直接调用 lambda,func(11) 来查看 11 是否属于其中。

          【讨论】:

            【解决方案6】:
            >>> print range.__doc__
            range([start,] stop[, step]) -> list of integers
            

            返回一个包含整数等差数列的列表。 range(i, j) 返回 [i, i+1, i+2, ..., j-1];开始 (!) 默认为 0。 当给定步长时,它指定增量(或减量)。 例如,range(4) 返回 [0, 1, 2, 3]。终点省略! 这些正是 4 个元素列表的有效索引。

            >>> range(33,44)
            [33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43]
            >>> range(1,3)
            [1, 2]
            

            我想你可以迭代你的列表,并适当地调用范围。

            >>> def lessThan(n) :
            ...  return range(n+1)
            ...
            >>> lessThan(4)
            [0, 1, 2, 3, 4]
            >>> def toFrom(n,m):
            ...  return range(n,m)
            ...
            >>> toFrom(33,44)
            [33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43]
            

            然后用逗号分割字符串,并为每一位解析它以找出要调用的函数,并将返回的列表连接起来。

            还有什么,我会写给你的。

            【讨论】:

              猜你喜欢
              • 2019-09-11
              • 2015-07-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-10-23
              • 2013-04-10
              • 2018-02-04
              相关资源
              最近更新 更多