【问题标题】:Python - expanding the range between dot dot (id1..id2)Python - 扩展点 dot (id1..id2) 之间的范围
【发布时间】:2016-09-07 20:33:43
【问题描述】:

假设我有一个 id 列表,例如:

ids= 1/1/n1..1/1/n5 , 1/1/x1 , 1/1/g1

预期输出:

1/1/n1 , 1/1/n2 , 1/1/n3 , 1/1/n4 , 1/1/n5 ,1/1/x1, 1/1/g1

意味着无论我在哪里找到'ids..ids',我都会填补空白

我已经写了一个非常基本的代码,但我正在寻找更多的pythonic解决方案

import re
ports_list=['1/1/n1..1/1/n8']

n = 2
port_range=[]
for port in ports_list:
    if '..' in port:
        groups = port.split('..')     #gives  ['1/1/n1', '1/1/n8']
        for item in groups:
            port_split = item.split('/')
            port_join='/'.join(port_split[:n]), '/'.join(port_split[n:])
            port_join=port_join[0]+"/"
            port_split=port_split[2]    # n1     n8
            get_str=port_split[0][0]
            num=re.findall(r'\d+', port_split) # 1 8
            port_range.append(num[0])
        #remove port with '..
        ports_list.remove(port)

n1=port_range[0]
n2=port_range[1]
final_number_list=list(range(int(n1),int(n2)+1))
my_new_list = [ get_str + str(n) for n in final_number_list]
final_list=[ port_join + str(n) for n in my_new_list]
ports_list=ports_list+final_list
print ports_list

给出预期的输出:

['1/1/n1', '1/1/n2', '1/1/n3', '1/1/n4', '1/1/n5', '1/1/n6', '1/1/n7', '1/1/n8']

但是如何在没有复杂逻辑的情况下轻松解决呢?

【问题讨论】:

    标签: python regex python-2.7 list


    【解决方案1】:

    不确定它是否比您当前的方法更具可读性或更好,但我们可以使用正则表达式从字符串中提取公共部分和范围边界:

    import re
    
    
    def expand(l):
        result = []
        pattern = re.compile(r"^(.*?)(\d+)$")
        for item in l:
            # determine if it is a "range" item or not
            is_range = '..' in item
            if not is_range:
                result.append(item)
                continue
    
            # get the borders and the common reusable part
            borders = [pattern.match(border).groups() for border in item.split('..')]
            (common_part, start), (_, end) = borders
    
            for x in range(int(start), int(end) + 1):
                result.append("%s%d" % (common_part, x))
    
        return result
    
    print(expand(['1/1/n1..1/1/n8']))
    print(expand(['1/1/n1..1/1/n5', '1/1/x1', '1/1/g1']))
    

    打印:

    ['1/1/n1', '1/1/n2', '1/1/n3', '1/1/n4', '1/1/n5', '1/1/n6', '1/1/n7', '1/1/n8']
    ['1/1/n1', '1/1/n2', '1/1/n3', '1/1/n4', '1/1/n5', '1/1/x1', '1/1/g1']
    

    ^(.*?)(\d+)$

    • ^ 匹配字符串的开头(在我们的例子中实际上不需要,因为我们使用.match() - 无论如何它都会从字符串的开头开始搜索 - 只是因为“显式优于隐式”而将其留在那里)李>
    • (.*?) 是一个捕获组,可以在 non-greedy fashion 中多次保存任何字符
    • (\d+) 是一个捕获组,可以保存一个或多个连续数字
    • $ 匹配字符串的结尾

    【讨论】:

      【解决方案2】:

      这是基本代码;我会让你根据需要重新组合它,包括你已经拥有的列表推导。就像你已经在做的那样分割范围。无需解构整个字符串,只需取最后一个数字并运行范围:

      ports_list=['1/1/n1..1/1/n8']
      
      for port in ports_list:
          if ".." in port:
              left, right = port.split("..")
              for i in range(int(left[-1]), int(right[-1])+1):
                  new_port = left[:-1] + str(i)
                  print new_port
      

      最后一行只是为了演示正确的响应。

      【讨论】:

      • 1/1/n11..1/1/n15 怎么样?
      • 它工作得很好。当有“carry”时不起作用,例如n18..n22,但问题描述中没有给出。
      猜你喜欢
      • 2015-07-12
      • 2019-06-19
      • 2020-06-15
      • 2011-08-13
      • 1970-01-01
      • 1970-01-01
      • 2014-09-20
      • 2019-06-09
      相关资源
      最近更新 更多