【问题标题】:Tricky way to split string by \t通过 \t 分割字符串的棘手方法
【发布时间】:2019-04-30 06:10:12
【问题描述】:

这样的字符串:

x = dir\tsubdir1\t\tfile1.ext\t\tsubsubdir1\tsubdir2\t\tsubsubdir2\t\t\tfile2.ext

如何将上面的字符串“pythonish/tricky”拆分成列表?

dir
\tsubdir1
\t\tfile1.ext
\t\tsubsubdir1
\tsubdir2
\t\tsubsubdir2
\t\t\tfile2.ext

['dir', '\tsubdir1', '\t\tfile1.ext', '\t\tsubsubdir1', '\tsubdir2', '\t\tsubsubdir2', '\t\t\tfile2.ext']

概念证明:

x = r'dir\tsubdir1\t\tfile1.ext\t\tsubsubdir1\tsubdir2\t\tsubsubdir2\t\t\tfile2.ext'
y = x.split(r'\t')
print(y)

【问题讨论】:

  • x.replace("\t"," ").split()
  • @kantal 会丢失所有 \t - 丢失它们是重点
  • @Patrick Artner 你是对的:-)

标签: python string python-3.x python-2.7 split


【解决方案1】:

也许使用正则表达式?

>>> import regex
>>> L = regex.split(r"(?<!\t)\t", "dir\tsubdir1\t\tfile1.ext\t\tsubsubdir1\tsubdir2\t\tsubsubdir2\t\t\tfile2.ext")
>>> L
['dir', 'subdir1', '\tfile1.ext', '\tsubsubdir1', 'subdir2', '\tsubsubdir2', '\t\tfile2.ext']
>>> L[:1] + ['\t' + i for i in L[1:]]
['dir', '\tsubdir1', '\t\tfile1.ext', '\t\tsubsubdir1', '\tsubdir2', '\t\tsubsubdir2', '\t\t\tfile2.ext']

它是如何工作的?

正则表达式是

(?<!\t)\t

这意味着“一个标签之前没有另一个标签”,因此标签序列中的每个第一个标签都由正则表达式匹配。然后将其用作分割标记。

拆分后,从每个后续项目中剥离一个选项卡,因此最后一行 L[:1] + ['\t' + i for i in L[1:]] 将丢失的选项卡放在前面。

【讨论】:

    【解决方案2】:

    您可以通过触摸 path 输入的每个字符一次 + 一些列表组合来做到这一点:

    path = "dir\tsubdir1\t\tfile1.ext\t\tsubsubdir1\tsubdir2\t\tsubsubdir2\t\t\tfile2.ext"
    
    l = [[]]
    for c in path:
        if c != "\t":              # append to last element of list if not a \t
            l[-1].append(c)
        elif l[-1][-1] == "\t":    # also append to last element of list if it's last is a \t
            l[-1].append(c)        # (you could 'or' it into the if before)
        else:
            l.append([])           # else create a new "word" and append the \t
            l[-1].append(c)
    
    l = [''.join(elem) for elem in l]   # join the things back together
    print(l)
    

    输出:

    ['dir', 
     '\tsubdir1', 
     '\t\tfile1.ext', 
     '\t\tsubsubdir1', 
     '\tsubdir2',
     '\t\tsubsubdir2', 
     '\t\t\tfile2.ext']
    

    在加入步骤之前,累积的列表如下所示:

    [['d', 'i', 'r'], 
     ['\t', 's', 'u', 'b', 'd', 'i', 'r', '1'], 
     ['\t', '\t', 'f', 'i', 'l', 'e', '1', '.', 'e', 'x', 't'], 
     ['\t', '\t', 's', 'u', 'b', 's', 'u', 'b', 'd', 'i', 'r', '1'], 
     ['\t', 's', 'u', 'b', 'd', 'i', 'r', '2'], 
     ['\t', '\t', 's', 'u', 'b', 's', 'u', 'b', 'd', 'i', 'r', '2'], 
     ['\t', '\t', '\t', 'f', 'i', 'l', 'e', '2', '.', 'e', 'x', 't']]
    

    您不想添加到字符串,因为它会创建大量中间“丢弃”字符串实例,这会减慢速度 - 使用列表更快且压力更小。

    【讨论】:

      【解决方案3】:
      import re
      
      x = 'dir\tsubdir1\t\tfile1.ext\t\tsubsubdir1\tsubdir2\t\tsubsubdir2\t\t\tfile2.ext'
      
      s = re.sub('([^\t])\t', '\\1\n\t', x).split('\n')
      
      print(s)
      

      输出:

      ['dir', '\tsubdir1', '\t\tfile1.ext', '\t\tsubsubdir1', '\tsubdir2', '\t\tsubsubdir2', '\t\t\tfile2.ext']
      

      【讨论】:

      • 我很好奇谁以及为什么对一个明显正确的答案投反对票。
      【解决方案4】:

      另一个使用 findall() 的正则表达式解决方案:

      x = dir\tsubdir1\t\tfile1.ext\t\tsubsubdir1\tsubdir2\t\tsubsubdir2\t\t\tfile2.ext
      re.findall(r"\t+[^\t]+|[^\t]+",x)                                                                                     
      Out: 
      ['dir',
       '\tsubdir1',
       '\t\tfile1.ext',
       '\t\tsubsubdir1',
       '\tsubdir2',
       '\t\tsubsubdir2',
       '\t\t\tfile2.ext']
      

      【讨论】:

        猜你喜欢
        • 2012-07-31
        • 2020-11-07
        • 1970-01-01
        • 2016-08-29
        • 1970-01-01
        • 2012-11-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多