1. ホーム
  2. python

[解決済み] Pythonで空の文字列を分割するとき、split()は空のリストを返すのに、split('˶'˶)は['']を返すのはなぜですか?

2022-04-21 21:10:17

質問

を使っています。 split('\n') を使用して、1つの文字列内の行を取得することができます。 ''.split() は空のリストを返します。 [] 一方 ''.split('\n') を返します。 [''] . このような違いが生じる具体的な理由はあるのでしょうか?

また、文字列の行数を数えるのに、もっと便利な方法はないのでしょうか?

どのように解決するのですか?

<ブロッククオート

質問です。 私は split('\n') を使用して、1つの文字列内の行を取得することができます。 ''.split() は空のリストを返します。 [] 一方 ''.split('\n') を返します。 [''] .

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

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

これに対して、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
['', '', '']

質問です。 また、文字列の行数を数えるのに、もっと便利な方法はないのでしょうか?

はい、簡単な方法がいくつかあります。 ひとつは 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    

カズさんからの質問です。なぜ、2つの異なるアルゴリズムが1つの関数に組み込まれているのでしょうか?

のシグネチャは str.split は約20年前のもので、その時代のAPIの多くは厳密に実用的なものです。完璧ではありませんが、このメソッドのシグネチャも"terrible"ではありません。ほとんどの場合、GuidoのAPI設計の選択は時の試練に耐えています。

現在のAPIにも利点がないわけではありません。 次のような文字列を考えてみましょう。

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

これらの文字列をフィールドに分割するように言われると、人はどちらも同じ英語、"split"を使って表現する傾向があります。次のようなコードを読むように言われた場合 fields = line.split() または fields = line.split(',') のように解釈されがちですが、これは「行をフィールドに分割する」という意味です。

マイクロソフト・エクセルの テキストから列への変換ツール は、同様のAPIを選択し 両方の分割アルゴリズムが同じツールに組み込まれています。複数のアルゴリズムが関与しているにもかかわらず、人々はフィールド分割を単一の概念として精神的にモデル化しているようです。