问题:在Python中拆分空字符串时,为什么split()返回空列表,而split(’\ n’)返回[”]?
我split('\n')
用来获取一个字符串中的行,并发现''.split()
返回一个空列表[]
,而''.split('\n')
return ['']
。有什么特殊原因造成这种差异?
还有没有更方便的方法来计算字符串中的行数?
回答 0
问题:我正在使用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']
注意,结果字段的数量比定界符的数量大一。想想剪一条绳子。如果不削减,则只有一件。一切,给出两块。进行两次切割,得到三块。Python的str.split(delimiter)方法也是如此:
>>> ''.split(',') # No cuts
['']
>>> ','.split(',') # One cut
['', '']
>>> ',,'.split(',') # Two cuts
['', '', '']
问题:还有什么更方便的方法来计算字符串中的行数?
是的,有两种简单的方法。一个使用str.count(),另一个使用str.splitlines()。除非最后一行缺少,否则两种方法都将给出相同的答案\n
。如果最后的换行符丢失,则str.splitlines方法将给出准确的答案。一种更快且更准确的技术是使用count方法,然后将其更正为最终的换行符:
>>> 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的“ 文本到列”工具做出了类似的API选择,并将两种分割算法都合并到了同一工具中。尽管似乎涉及多个算法,但人们似乎在思维上将字段拆分建模为一个单独的概念。
回答 1
根据文档,这似乎只是它应该工作的方式:
使用指定的分隔符分割空字符串将返回
['']
。如果未指定sep或为None,则将应用不同的拆分算法:连续的空白行将被视为单个分隔符,并且如果字符串的开头或结尾处有空白,则结果在开头或结尾将不包含空字符串。因此,使用None分隔符拆分空字符串或仅包含空格的字符串将返回[]。
因此,为了更清楚一点,该split()
函数实现了两种不同的拆分算法,并使用参数的存在来决定要运行哪个参数。这可能是因为它允许优化一个不带参数的参数,而不是优化带参数的参数。我不知道。
回答 2
.split()
没有参数的人会变得聪明。它在任何空格,制表符,空格,换行符等处分割,并因此跳过所有空字符串。
>>> " fii fbar \n bopp ".split()
['fii', 'fbar', 'bopp']
本质上,.split()
不带参数的用于从字符串中提取单词,而.split()
带参数的参数只是带一个字符串并将其分割。
这就是差异的原因。
是的,通过分割来计数行不是一种有效的方法。计算换行符的数量,如果字符串不以换行符结尾,则加一个。
回答 3
用途count()
:
s = "Line 1\nLine2\nLine3"
n_lines = s.count('\n') + 1
回答 4
>>> 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
要计算行数,可以计算换行数:
n_lines = sum(1 for s in the_string if s == "\n") + 1 # add 1 for last line
编辑:
内置的另一个答案count
更合适,实际上