【问题标题】:How to split a string at line breaks in python?如何在python中的换行符处拆分字符串?
【发布时间】:2014-01-18 13:56:19
【问题描述】:

我想将一些表格数据从 Excel 复制到 python 数组中。也就是说,用户将在 Excel 表格中选择一个范围,按“复制”(CTRL+C) 以便将该范围复制到剪贴板。然后我将这个剪贴板数据放入一个 python 数组(列表)中。我使用win32clipboardfrom pywin32 将剪贴板数据放入数组中:

import win32clipboard

def getClip():
    win32clipboard.OpenClipboard()
    data = win32clipboard.GetClipboardData()
    win32clipboard.CloseClipboard()
    return data

我从 Excel 复制以下范围 A1:B5

当我使用上面的函数时,我得到一个字符串:

'365\t179\r\n96\t-90\r\n48\t-138\r\n12\t-174\r\n30\t-156\r\n'

如何把这个字符串拆分成一个列表,让列表看起来像:

[(365,179), (96, -90), (48, -138), (12, -174), (30, -156)]

我使用split 方法,但它没有给我想要的。

data.split("\n")

['365\t179\r', '96\t-90\r', '48\t-138\r', '12\t-174\r', '30\t-156\r', '']

【问题讨论】:

    标签: python arrays list clipboard pywin32


    【解决方案1】:

    实际上有一个str.splitlines 方法,它会通过换行符来分割字符串,而不管使用了哪些换行符。所以这适用于只有 \n 的 Unix 系统,在带有 \r\n 的 Windows 上,甚至在换行符只是 \r 的旧 Mac 系统上。

    >>> s = '365\t179\r\n96\t-90\r\n48\t-138\r\n12\t-174\r\n30\t-156\r\n'
    >>> s.splitlines()
    ['365\t179', '96\t-90', '48\t-138', '12\t-174', '30\t-156']
    

    获得此结果后,您可以按标签拆分以获取各个单元格。所以你基本上必须在每个单元格上调用cell.split('\t')。最好通过列表理解来完成:

    >>> [row.split('\t') for row in s.splitlines()]
    [['365', '179'], ['96', '-90'], ['48', '-138'], ['12', '-174'], ['30', '-156']]
    

    您也可以使用map 对每个单元格应用拆分操作:

    >>> list(map(lambda cell: cell.split('\t'), s.splitlines()))
    [['365', '179'], ['96', '-90'], ['48', '-138'], ['12', '-174'], ['30', '-156']]
    

    由于剪贴板中复制的数据将始终具有由换行符分隔的行和由制表符分隔的列,因此此解决方案也可以安全地用于您复制的任何单元格范围。

    如果您还想在 Python 中将整数或浮点数转换为正确的数据类型,我想您可以通过在所有只有数字的单元格上调用 int() 来添加更多转换逻辑,在所有单元格上调用 float()有数字和其中的点.,其余为字符串:

    >>> def convert (cell):
            try:
                return int(cell)
            except ValueError:
                try:
                    return float(cell)
                except ValueError:
                    return cell
    >>> [tuple(map(convert, row.split('\t'))) for row in s.splitlines()]
    [(365, 179), (96, -90), (48, -138), (12, -174), (30, -156)]
    

    对于不同的字符串:

    >>> s = 'Foo\tbar\r\n123.45\t42\r\n-85\t3.14'
    >>> [tuple(map(convert, row.split('\t'))) for row in s.splitlines()]
    [('Foo', 'bar'), (123.45, 42), (-85, 3.14)]
    

    【讨论】:

      【解决方案2】:
      >>> s = '365\t179\r\n96\t-90\r\n48\t-138\r\n12\t-174\r\n30\t-156\r\n'
      >>> [map(int, x.split('\t')) for x in s.rstrip().split('\r\n')]
      [[365, 179], [96, -90], [48, -138], [12, -174], [30, -156]]
      

      使用我other answer的代码,你也可以处理其他类型:

      from ast import literal_eval
      def solve(x):
          try:
              return literal_eval(x)
          except (ValueError, SyntaxError):
              return x
      
      s = '365\tFoo\r\nBar\t-90.01\r\n48\tspam\r\n12e10\t-174\r\n30\t-156\r\n'
      print [map(solve, x.split('\t')) for x in s.rstrip().split('\r\n')]
      #[[365, 'Foo'], ['Bar', -90.01], [48, 'spam'], [120000000000.0, -174], [30, -156]]
      

      【讨论】:

      • 如果复制的 Excel 范围有 5 行 10 列怎么办?那么列表应该有 5 个内部列表,每个内部列表应该有 10 个项目。你的解决方案会提供这个吗?
      • @alwbtc 是的。它会:)
      • 好的,但是如果范围同时包含字符串和整数怎么办?
      • 对,我应该在那个范围内包含一些字符串。但是一个单独的问题不会与这个问题重复吗?
      • @alwbtc 在这种情况下,将内部项目传递给 ast.literal_eval 而不是 map(int..
      【解决方案3】:
      d = '365\t179\r\n96\t-90\r\n48\t-138\r\n12\t-174\r\n30\t-156\r\n'
      print [tuple(map(int,item.split(","))) for item in d.replace("\t", ",").split()]
      

      输出

      [(365, 179), (96, -90), (48, -138), (12, -174), (30, -156)]
      

      【讨论】:

        【解决方案4】:
        In [85]: zip(*[iter(map(int, data.split()))]*2)
        Out[85]: [(365, 179), (96, -90), (48, -138), (12, -174), (30, -156)]
        

        下面是它的工作原理:

        首先,按空格分割:

        In [86]: data.split()
        Out[86]: ['365', '179', '96', '-90', '48', '-138', '12', '-174', '30', '-156']
        

        将字符串转换为整数:

        In [87]: map(int, data.split())
        Out[87]: [365, 179, 96, -90, 48, -138, 12, -174, 30, -156]
        

        使用grouper recipe 对每 2 个项目进行分组:

        In [88]: zip(*[iter(map(int, data.split()))]*2)
        Out[88]: [(365, 179), (96, -90), (48, -138), (12, -174), (30, -156)]
        

        【讨论】:

        • 如果复制的 Excel 范围有 5 行 10 列怎么办?那么列表应该有 5 个元组,每个元组应该有 10 个项目。你的解决方案会提供这个吗?
        • @alwbtc:可以,但是您必须将石斑鱼配方中的 2 更改为 10。如果您不知道每个元组中应该有多少项目,那么在 \t 上拆分的解决方案会更好。
        【解决方案5】:
        [line.split() for line in my_str.split("\n")]
        

        这只是将数据分成几行,然后根据空白进行拆分。检查出来,根据你的数据修改。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-08-05
          • 1970-01-01
          • 1970-01-01
          • 2013-08-30
          • 1970-01-01
          • 2018-01-24
          • 2015-02-25
          • 1970-01-01
          相关资源
          最近更新 更多