Python使用至少两个空格来分割字符串

47
我想要仅在至少有两个或更多空格的位置拆分一个字符串。
例如:
str = '10DEUTSCH        GGS Neue Heide 25-27     Wahn-Heide   -1      -1'
print(str.split())

结果:

['10DEUTSCH', 'GGS', 'Neue', 'Heide', '25-27', 'Wahn-Heide', '-1', '-1']
我希望它看起来像这样:
['10DEUTSCH', 'GGS Neue Heide 25-27', 'Wahn-Heide', '-1', '-1']
5个回答

85
>>> import re    
>>> text = '10DEUTSCH        GGS Neue Heide 25-27     Wahn-Heide   -1      -1'
>>> re.split(r'\s{2,}', text)
['10DEUTSCH', 'GGS Neue Heide 25-27', 'Wahn-Heide', '-1', '-1']

在哪里

  • \s 匹配任何空白字符,例如 \t\n\r\f\v 等等
  • {2,}重复,表示“2个或更多”

1
不需要使用正则表达式,只需使用“str.split(' ')”即可。另外请注意,使用“str”作为变量名是不好的,因为它是内置的“str”类型。 - Wessie
10
"text.split(' ')" 会产生大量空字符串,因为空格数通常大于2。 - unutbu
str.split(' ') 的结果为 ['10DEUTSCH', '', '', '', 'GGS Neue Heide 25-27', '', ' Wahn-Heide', ' -1', '', '', '-1']。正则表达式是在“2 或更多个空格”上拆分的好方法。 - dokkaebi
@JohnY 绝对正确,我不知道是什么让我在没有 pandas 标签的情况下改变了答案 - 很好的修复。 - Umar.H
如果你正在从文本文件中读取字符串,并且你需要忽略换行符,那么re.split(r'\s{2,}', text.replace("\n", ""))可能会有用。 - KevinYanesG

11

正如已经指出的那样,str 不是一个好的变量名称,因此使用 words 替代:

output = [s.strip() for s in words.split('  ') if s]
.split(' ')会返回一个包含空字符串和带有前导/尾随空格项的列表。该列表推导式遍历该列表,保留任何非空白项(if s),.strip()处理任何前导/尾随空格。

1
我认为你还需要加上 .strip() 来防止 " -1" 的出现(请参考 @Ashwini 的解决方案)。 - DSM
map(lambda s: s.strip(), filter(None, words.split())) 可以作为更快的替代方案,尽管不够易读。 - Axel Advento

5
In [30]: strs='10DEUTSCH        GGS Neue Heide 25-27     Wahn-Heide   -1      -1'

In [38]: filter(None, strs.split("  "))

Out[38]: ['10DEUTSCH', 'GGS Neue Heide 25-27', ' Wahn-Heide', ' -1', '-1']

In [32]: map(str.strip, filter(None, strs.split("  ")))

Out[32]: ['10DEUTSCH', 'GGS Neue Heide 25-27', 'Wahn-Heide', '-1', '-1']

对于Python 3,使用listfiltermap的结果包装起来可以强制执行迭代。


1

在以下情况下:

  • 制表符和空格混合使用
  • 字符串开头和/或结尾有空格

(最初回答Python中将字符串按超过单个空格和制表符的空格分割)

我会使用正则表达式进行拆分:2个或更多空格,然后过滤掉re.split生成的空字符串:

import re

s = '        1. 1. 2.     1 \tNote#EvE\t \t1\t \tE3\t \t  64\t        1. 3. 2. 120 \n'

result = [x for x in re.split("\s{2,}",s) if x]

print(result)

打印:

['1. 1. 2.', '1', 'Note#EvE', '1', 'E3', '64', '1. 3. 2. 120']

这不会保留前导/尾随空格,但接近。

0

之前给出的基于列表推导式的解决方案存在一个小缺陷。如果输入中有尾随空格,则拆分可能会产生最后一个元素,该元素仅包含单个空格(或少于n个空格的某些空格数量,其中n是要拆分的最小空格数),Python在布尔上下文中将其视为True。因此,输出中的最后一个元素可能是不需要的空字符串:

>>> s = '10DEUTSCH        GGS Neue Heide 25-27     Wahn-Heide   -1      -1   '
>>> [t.strip() for t in s.split('  ') if t]
['10DEUTSCH', 'GGS Neue Heide 25-27', 'Wahn-Heide', '-1', '-1', '']

有几种方法可以解决这个问题。其中一种是在检查其真实性之前剥离由split返回的每个元素:

>>> s = '10DEUTSCH        GGS Neue Heide 25-27     Wahn-Heide   -1      -1   '
>>> [t.strip() for t in s.split('  ') if t.strip()]
['10DEUTSCH', 'GGS Neue Heide 25-27', 'Wahn-Heide', '-1', '-1']

但是每个标记都剥离两次看起来有点丑陋。因此,另一种方法是在开始时只剥离输入:

>>> s = '10DEUTSCH        GGS Neue Heide 25-27     Wahn-Heide   -1      -1   '
>>> [t.strip() for t in s.strip().split('  ') if t]
['10DEUTSCH', 'GGS Neue Heide 25-27', 'Wahn-Heide', '-1', '-1']

如果你想使用列表推导式,那应该已经足够了。但是如果你对精确性有着不健康的追求,也许你会注意到由于拆分是从左到右进行的,每个拆分结果中的标记只能有前导空格,并且不需要的空字符串只能出现在最终输出的末尾。因此,如果你认为这多两个字符是值得的,你可以选择

>>> s = '10DEUTSCH        GGS Neue Heide 25-27     Wahn-Heide   -1      -1   '
>>> [t.lstrip() for t in s.rstrip().split('  ') if t]
['10DEUTSCH', 'GGS Neue Heide 25-27', 'Wahn-Heide', '-1', '-1']

如果您使用的是 Python 3.8+,您可以使用海象操作符来避免冗余的剥离:
>>> s = '10DEUTSCH        GGS Neue Heide 25-27     Wahn-Heide   -1      -1   '
>>> [w for t in s.split('  ') if (w := t.strip())]
['10DEUTSCH', 'GGS Neue Heide 25-27', 'Wahn-Heide', '-1', '-1']

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接