2013-05-20 18 views
115

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

有没有更方便的方法来计算字符串中的行数?

+0

可能的重复[为什么在split()结果中返回空字符串?](https://stackoverflow.com/questions/2197451/why-are-empty-strings-returned-in-split-results) –

回答

193

问:我使用的分裂( '\ 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'] 

请注意,结果字段的数量比分隔符的数量多一个。想想切割一根绳子。如果你没有削减,你有一块。做一个切割,给出两块。做两个切割,给出三块。 因此,这是Python的str.split(分隔符)方法:

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

问:那么有没有更方便的方法来计算一个串线?

是的,有几个简单的方法。一个使用str.count(),另一个使用str.splitlines()。 两种方法都会给出相同的答案,除非最后一行缺少\n。 如果最后的换行符丢失,str.splitlines方法会给出准确的答案。 更快的技术,这也是正确的使用计数法,但随后修正它最终换行:从@Kaz

>>> 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  

问:为什么赫克是两个完全不同的算法鞋独角成一个单一的功能?

str.split签名是20岁左右,和一些从那个时代的API都是从严务实。 虽然不完美,但方法签名也不“可怕”。 绝大多数情况下,Guido的API设计选择经受住了时间的考验。

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

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

当记者问到打破这些字符串放到领域, 人们往往使用相同的英文单词,“分裂”既来形容。 当被要求阅读诸如fields = line.split()fields = line.split(','), 之类的代码时,人们倾向于正确地将语句 解释为“将行分割为字段”。

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

26

这似乎仅仅是它应该工作,根据the documentation方式:

分割一个空字符串以指定的分隔符返回['']

如果未指定sep或为None,则应用不同的分割算法:将连续空白的运行视为单个分隔符,并且如果该字符串具有前导或结果,则开始或结束时不会包含空字符串或尾随空白。因此,将空字符串或只包含空格的字符串拆分为无分隔符将返回[]。

所以,使其更清晰,在split()功能实现两个不同的分割算法,并使用一个参数的存在来决定运行哪一个。这可能是因为它允许优化没有参数的参数而不是带参数的参数。我不知道。

0

计算行,你可以指望的换行符号:

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

编辑

The other answer具有内置count更适合,其实

+3

Aside从使用'count'开始,bools是可添加的(事实上,它们是子类'int'),所以genexp可以写成sum(s ==“\ n”用于s_string中的s)''。 – lvc

+0

真的,很好的评论 –

+0

现在你只是数空行吗? –

2

使用count()

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

+ 1只应在文本不以'\ n'结尾时完成。 –

+7

那么,如果它以“\ n”结尾,那么最后一行是空行。虽然没用,但它仍然算作线,不是? –

+2

没有。当我将3行文本写入文件并用换行结束每一行时,我会说该文件包含3行。在unix上,最好有一个文本文件总是以换行结束。否则'猫文件'乱糟糟的命令行和颠覆抱怨。 vi总是追加一个。 – user829755

3

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

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

实质上,.split()而不参数用于从字符串中提取单词,而不是.split()与只采用一个字符串并拆分它的参数。

这就是差异的原因。

是的,通过分割计数行不是一种有效的方法。计算换行的数量,如果字符串不以换行符结束,则添加一个换行。

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的计数中。

相关问题