【问题标题】:How to convert numeric string ranges to a list in Python如何在 Python 中将数字字符串范围转换为列表
【发布时间】:2011-09-18 07:29:29
【问题描述】:

我希望能够将诸如“1,2,5-7,10”之类的字符串转换为诸如[1,2,5,6,7,10]之类的python列表。我环顾四周,找到了this,但我想知道在 Python 中是否有一种干净简单的方法可以做到这一点。

【问题讨论】:

    标签: python list string


    【解决方案1】:
    def f(x):
        result = []
        for part in x.split(','):
            if '-' in part:
                a, b = part.split('-')
                a, b = int(a), int(b)
                result.extend(range(a, b + 1))
            else:
                a = int(part)
                result.append(a)
        return result
    
    >>> f('1,2,5-7,10')
    [1, 2, 5, 6, 7, 10]
    

    【讨论】:

    • 这将是一个不错的生成器。
    • 通过用elif part != '':替换else来实现不爆炸前导或尾随逗号
    【解决方案2】:

    这可能有点矫枉过正,但我​​只是喜欢 pyparsing:

    from pyparsing import *
    
    def return_range(strg, loc, toks):
        if len(toks)==1:
            return int(toks[0])
        else:
            return range(int(toks[0]), int(toks[1])+1)
    def parsestring(s):
        expr = Forward()
        term = (Word(nums) + Optional(Literal('-').suppress() + Word(nums))).setParseAction(return_range)
        expr << term + Optional(Literal(',').suppress() + expr)
        return expr.parseString(s, parseAll=True)
    
    if __name__=='__main__':
        print parsestring('1,2,5-7,10')
    

    【讨论】:

      【解决方案3】:

      我能够对那个问题做出正确的理解:

      >>> def f(s):
          return sum(((list(range(*[int(j) + k for k,j in enumerate(i.split('-'))]))
               if '-' in i else [int(i)]) for i in s.split(',')), [])
      
      >>> f('1,2,5-7,10')
      [1, 2, 5, 6, 7, 10]
      
      >>> f('1,3-7,10,11-15')
      [1, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15]
      

      另一个假装理解的答案只是一个 for 循环,因为最终列表被丢弃了。 :)

      对于python 2,您甚至可以删除对list的调用!

      【讨论】:

        【解决方案4】:

        呃,答案太冗长了!这是一个简短而优雅的答案:

        def rangeString(commaString):
            def hyphenRange(hyphenString):
                x = [int(x) for x in hyphenString.split('-')]
                return range(x[0], x[-1]+1)
            return chain(*[hyphenRange(r) for r in commaString.split(',')])
        

        演示:

        >>> list( f('1,2,5-7,10') )
        [1, 2, 5, 6, 7, 10]
        

        易于修改以处理负数或返回列表。还需要from itertools import chain,但如果您不使用range 对象(或sum(map(list,iters),[]))并且您不在乎懒惰,您可以用sum(...,[]) 代替它。

        【讨论】:

          【解决方案5】:

          没有比我更好的理解力了!

          import re
          def convert(x):
              return sum((i if len(i) == 1 else list(range(i[0], i[1]+1))
                         for i in ([int(j) for j in i if j] for i in
                         re.findall('(\d+),?(?:-(\d+))?', x))), [])
          

          最好的部分是我在理解的中间使用了变量i 两次。

          >>> convert('1,2,5-7,10')
          [1, 2, 5, 6, 7, 10]
          

          【讨论】:

            【解决方案6】:

            非常简短,优雅(恕我直言):

            >>> txt = "1,2,5-7,10"
            >>> # construct list of xranges
            >>> xranges = [(lambda l: xrange(l[0], l[-1]+1))(map(int, r.split('-'))) for r in txt.split(',')]
            >>> # flatten list of xranges
            >>> [y for x in xranges for y in x]
            [1, 2, 5, 6, 7, 10]
            

            【讨论】:

              【解决方案7】:

              从这里:https://gist.github.com/raczben/76cd1229504d82115e6427e00cf4742c

              def number(a, just_try=False):
                  """
                  Parse any representation of number from string.
                  """
                  try:
                      # First, we try to convert to integer.
                      # (Note, that all integer can be interpreted as float and hex number.)
                      return int(a)
                  except:
                      # The order of the following convertions doesn't matter.
                      # The integer convertion has failed because `a` contains hex digits [x,a-f] or a decimal
                      # point ['.'], but not both.
                      try:
                          return int(a, 16)
                      except:
                          try:
                              return float(a)
                          except:
                              if just_try:
                                  return a
                              else:
                                  raise
              
              
              def str2numlist(s):
                  """
                  Convert a string parameter to iterable object.
                  """
                  return [y for x in s.split(',') for y in str_ranges_to_list(x) ]
              
              
              def str_ranges_to_list(s):
                  """
                  Convert a string parameter to iterable object.
                  """
                  s = s.strip()
                  try:
                      begin,end=s.split(':')
                      return range(number(begin), number(end))
                  except ValueError: # not enough values to unpack
                      return [number(s)]
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2012-04-08
                • 1970-01-01
                • 2018-01-19
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多