2013-05-20 17 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的計數中。

相關問題