在Python中拆分空字符串时,为什么split()返回空列表而split('\ n')返回['']?

时间:2013-05-20 08:02:33

标签: python string algorithm parsing split

我使用split('\n')获取一个字符串中的行,并发现''.split()返回一个空列表[],而''.split('\n')返回['']。有这种差异的具体原因吗?

还有更方便的方法来计算字符串中的行吗?

6 个答案:

答案 0 :(得分:209)

  

问题:我使用split('\ n')来获取一个字符串中的行,并找到了   ''.split()返回空列表[],而'.split('\ n')返回['']。

str.split()方法有两种算法。如果没有给出参数,它会在重复的空格运行时分裂。但是,如果给出了参数,则将其视为单个分隔符,不会重复运行。

在拆分空字符串的情况下,第一个模式(无参数)将返回一个空列表,因为吃了空格并且没有值放在结果列表中。

相反,第二种模式(带有\n等参数)将产生第一个空字段。考虑一下你是否写过'\n'.split('\n'),你会得到两个字段(一个分割,给你两半)。

  

问题:这种差异有什么具体原因吗?

当数据在具有可变数量的空格的列中对齐时,第一种模式很有用。例如:

>>> data = '''\
Shasta      California     14,200
McKinley    Alaska         20,300
Fuji        Japan          12,400
'''
>>> for line in data.splitlines():
        print line.split()

['Shasta', 'California', '14,200']
['McKinley', 'Alaska', '20,300']
['Fuji', 'Japan', '12,400']

第二种模式对于CSV等分隔数据非常有用,其中重复的逗号表示空字段。例如:

>>> data = '''\
Guido,BDFL,,Amsterdam
Barry,FLUFL,,USA
Tim,,,USA
'''
>>> for line in data.splitlines():
        print line.split(',')

['Guido', 'BDFL', '', 'Amsterdam']
['Barry', 'FLUFL', '', 'USA']
['Tim', '', '', 'USA']

注意,结果字段的数量比分隔符的数量大1。想想切割一根绳子。如果你没有削减,你就有一件。做一个切,给两件。做两次切割,给出三件。 所以它是Python的 str.split(分隔符)方法:

>>> ''.split(',')       # No cuts
['']
>>> ','.split(',')      # One cut
['', '']
>>> ',,'.split(',')     # Two cuts
['', '', '']
  

问题:是否有更方便的方法来计算字符串中的行?

是的,有几种简单的方法。一个使用str.count(),另一个使用str.splitlines()。 除非最后一行缺少\n,否则两种方式都会给出相同的答案。 如果缺少最终换行符, str.splitlines 方法将给出准确的答案。 更准确的更快速技术使用计数方法,但随后将其更正为最终换行符:

>>> data = '''\
Line 1
Line 2
Line 3
Line 4'''

>>> data.count('\n')                               # Inaccurate
3
>>> len(data.splitlines())                         # Accurate, but slow
4
>>> data.count('\n') + (not data.endswith('\n'))   # Accurate and fast
4    
  

来自@Kaz的问题:为什么这两种截然不同的算法只能用于单一功能?

str.split 的签名大约有20年的历史,而那个时代的许多API都是严格务实的。 虽然不完美,但方法签名也不是“可怕的”。 在大多数情况下,Guido的API设计选择经得起时间的考验。

当前的API并非没有优势。考虑如下字符串:

ps_aux_header  = "USER               PID  %CPU %MEM      VSZ"
patient_header = "name,age,height,weight"

当被要求将这些字符串分解为字段时, 人们倾向于使用相同的英文单词“split”来描述。 当被要求阅读fields = line.split()等代码时 或fields = line.split(','), 人们倾向于正确地解释这些陈述 作为“将一条线分成字段”。

Microsoft Excel的text-to-columns tool做出了类似的API选择 在同一工具中包含两种拆分算法。 人们似乎在精神上模拟场分裂 作为一个单一的概念,即使涉及多个算法。

答案 1 :(得分:28)

根据{{​​3}}:

,它似乎只是它的工作方式
  

使用指定的分隔符拆分空字符串将返回['']

     

如果未指定sep或为None,则应用不同的拆分算法:连续空格的运行被视为单个分隔符,如果字符串具有前导或尾随,则结果将在开头或结尾处不包含空字符串空白。因此,将空字符串或仅由空格组成的字符串拆分为无分隔符将返回[]。

因此,为了更清楚,split()函数实现了两种不同的分裂算法,并使用参数的存在来决定运行哪一种。这可能是因为它允许优先于没有参数的参数优于带参数的参数;我不知道。

答案 2 :(得分:3)

没有参数的

.split()试图变得聪明。它会拆分任何空格,制表符,空格,换行符等,并且它也会跳过所有空字符串。

>>> "  fii    fbar \n bopp ".split()
['fii', 'fbar', 'bopp']

基本上,没有参数的.split()用于从字符串中提取单词,而不是.split(),其参数只接受字符串并将其拆分。

这就是差异的原因。

是的,通过分裂来计算线条并不是一种有效的方法。计算换行符的数量,如果字符串不以换行符结尾,则添加一行。

答案 3 :(得分:2)

使用count()

s = "Line 1\nLine2\nLine3"
n_lines = s.count('\n') + 1

答案 4 :(得分:1)

>>> print str.split.__doc__
S.split([sep [,maxsplit]]) -> list of strings

Return a list of the words in the string S, using sep as the
delimiter string.  If maxsplit is given, at most maxsplit
splits are done. If sep is not specified or is None, any
whitespace string is a separator and empty strings are removed
from the result.

请注意最后一句。

要计算线数,您只需计算出\n的数量:

line_count = some_string.count('\n') + some_string[-1] != '\n'

最后一部分考虑了不以\n结尾的最后一行,即使这意味着Hello, World!Hello, World!\n具有相同的行数(对我来说这是合理的) ),否则您只需将1添加到\n的计数。

答案 5 :(得分:0)

要计算行数,您可以计算换行次数:

n_lines = sum(1 for s in the_string if s == "\n") + 1 # add 1 for last line

修改

内置count

The other answer更合适,实际上