179

私はsplit('\n')1つの文字列で行を取得するために使用してい''.split()ますが、空のリストを返す[]こと''.split('\n')がわかりました['']. このような違いには何か特別な理由がありますか?

また、文字列の行を数える便利な方法はありますか?

4

6 に答える 6

269

質問: を使用split('\n')して 1 つの文字列で行を取得してい''.split()ますが、 が空のリストを返し[]、 を''.split('\n')返します['']

メソッドには 2 つのstr.split()アルゴリズムがあります。引数が指定されていない場合、空白の繰り返し実行で分割されます。ただし、引数が指定されている場合は、繰り返し実行されない単一の区切り文字として扱われます。

空の文字列を分割する場合、最初のモード (引数なし) は、空白が消費され、結果リストに入れる値がないため、空のリストを返します。

対照的に、2 番目のモード ( などの引数を使用\n) では、最初の空のフィールドが生成されます。を書いた場合を考えてみましょ'\n'.split('\n')う。2 つのフィールドが得られます (1 つの分割で 2 つの半分になります)。

質問: このような違いには何か特別な理由はありますか?

この最初のモードは、可変量の空白を使用してデータが列に配置される場合に役立ちます。例えば:

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

2 番目のモードは、繰り返されるコンマが空のフィールドを表す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 大きいことに注意してください。ロープを切ることを考えてください。カットをしない場合は、1 つのピースがあります。1回のカットで2枚になります。2 つのカットを作ると、3 つのピースが得られます。Python のstr.split(delimiter)メソッドも同様です。

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

質問: 文字列の行を数えるもっと便利な方法はありますか?

はい、簡単な方法がいくつかあります。1 つは を使用str.count()し、もう 1 つは を使用します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 からの質問: 一体なぜ、2 つの非常に異なるアルゴリズムが 1 つの関数に詰め込まれているのでしょうか?

の署名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 ツールは、同様の API を選択し、両方の分割アルゴリズムを同じツールに組み込んでいます。複数のアルゴリズムが関係しているにもかかわらず、人々は精神的にフィールド分割を単一の概念としてモデル化しているようです。

于 2013-05-20T08:18:51.313 に答える
5

.split()パラメータなしで賢くしようとします。空白、タブ、スペース、改行などで分割され、その結果として空の文字列もすべてスキップされます。

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

本質的に、文字列を取得して分割するだけのパラメータを使用するのと.split()は対照的に、パラメータを使用せずに文字列から単語を抽出するために使用されます。.split()

それが違いの理由です。

そうです、分割して行を数えることは効率的な方法ではありません。改行の数をカウントし、文字列が改行で終わらない場合は 1 つ追加します。

于 2013-05-20T08:13:01.090 に答える
2
>>> 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

于 2013-05-20T12:01:59.490 に答える
2

使用count():

s = "Line 1\nLine2\nLine3"
n_lines = s.count('\n') + 1
于 2013-05-20T08:09:47.747 に答える