Python'da boş bir dizeyi bölerken, split ('\ n') [''] döndürürken neden split () boş bir liste döndürür?


Yanıtlar:


247

Soru: Bir dizede satır almak için split ('\ n') kullanıyorum ve '' .split () boş liste [] döndürürken, '' .split ('\ n') [''] döndürdü .

Str.split () metodu iki algoritmaları bulunmaktadır. Herhangi bir argüman verilmezse, tekrarlanan boşluk alanlarına ayrılır. Ancak, bir argüman verilirse, yinelenen çalışma olmadan tek bir sınırlayıcı olarak ele alınır.

Boş bir dizenin bölünmesi durumunda, beyaz alan yenildiği ve sonuç listesine konacak değer olmadığından ilk mod (bağımsız değişken yok) boş bir liste döndürür.

Buna karşılık, ikinci mod (gibi bir argümanla \n) ilk boş alanı oluşturur. Yazmış olsaydınız '\n'.split('\n'), iki alan elde edeceğinizi düşünün (bir bölme, size iki yarı verir).

Soru: Böyle bir farkın belirli bir nedeni var mı?

Bu ilk mod, veriler değişken miktarlarda boşluk içeren sütunlarda hizalandığında yararlıdır. Örneğin:

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

İkinci mod, tekrarlanan virgüllerin boş alanları gösterdiği CSV gibi sınırlandırılmış veriler için kullanışlıdır. Örneğin:

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

Sonuç alanlarının sayısının, sınırlayıcı sayısından bir fazla olduğunu unutmayın. Bir ip kesmeyi düşünün. Kesim yapmazsan, bir parçan var. Bir kesim yapmak, iki parça verir. İki kesim yapmak, üç parça verir. Ve böylece Python'un str.split (ayırıcı) yöntemi ile:

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

Soru: Bir dizedeki çizgileri saymanın daha uygun bir yolu var mı?

Evet, birkaç kolay yol var. Birinde str.count () kullanılır , diğerinde str.splitlines () kullanılır . Son satırda eksik olmadıkça her iki yol da aynı cevabı verecektir \n. Eğer son satırsonu eksikse, str.splitlines yaklaşımı doğru cevabı verecektir. Aynı zamanda doğru olan daha hızlı bir teknik sayma yöntemini kullanır, ancak daha sonra son satırsonu için düzeltir:

>>> 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'dan Soru: Neden halt tek bir fonksiyona ayakkabı boynuzlu iki farklı algoritma?

Str.split imzası yaklaşık 20 yaşındadır ve o döneme ait bazı API'lar kesinlikle pragmatiktir. Mükemmel olmasa da, yöntem imzası da "korkunç" değildir. Çoğunlukla, Guido'nun API tasarım seçenekleri zaman testini gerçekleştirdi.

Mevcut API'nin avantajları yoktur. Aşağıdaki gibi dizeleri düşünün:

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

Bu dizeleri alanlara ayırmanız istendiğinde, insanlar her ikisini de aynı İngilizce kelime olan "split" i kullanarak tanımlama eğilimindedir. fields = line.split() Veya gibi bir kod okuması istendiğinde fields = line.split(','), insanlar ifadeleri "bir satırı alanlara ayırır" şeklinde doğru yorumlama eğilimindedir.

Microsoft Excel'in metin-sütun aracı benzer bir API seçimi yaptı ve her iki bölme algoritmasını da aynı araçta birleştirdi. Birden fazla algoritma olmasına rağmen, insanlar zihinsel olarak bölünmeyi tek bir kavram olarak modelliyor gibi görünmektedir.


28

Belgelere göre, basitçe çalışması gerektiği gibi görünüyor :

Boş bir dizeyi belirtilen bir ayırıcıyla bölmek döndürür [''].

Sep belirtilmezse veya None ise, farklı bir bölme algoritması uygulanır: ardışık boşluk alanlarının çalışması tek bir ayırıcı olarak kabul edilir ve dize önde gelen veya sondaki boşluk varsa sonuçta başlangıç ​​veya bitişte boş dizeler bulunmaz. Sonuç olarak, boş bir dizeyi veya yalnızca boşluktan oluşan bir dizeyi Hiçbiri ayırıcıyla bölmek [] döndürür.

Bu nedenle, daha net hale getirmek için, split()işlev iki farklı bölme algoritması uygular ve hangisinin çalıştırılacağına karar vermek için bir argümanın varlığını kullanır. Bunun nedeni, argümanı argümanlı olandan daha fazla argüman için optimize etmemesine izin vermesi olabilir; Bilmiyorum.


4

.split()parametreler olmadan zeki olmaya çalışır. Herhangi bir boşluk, sekme, boşluk, satır beslemesi vb. Üzerine bölünür ve bunun sonucunda boş dizeleri de atlar.

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

Temelde, .split()parametreler olmadan bir dizeden sözcükleri ayıklamak için kullanılır, aksine .split()bir dizeyi alıp böler.

Farkın nedeni budur.

Ve evet, çizgileri bölerek saymak etkili bir yol değildir. Satır feed'lerinin sayısını sayın ve dize bir satır feed'i ile bitmiyorsa bir tane ekleyin.


2

Kullanım count():

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

4
+ 1 yalnızca metin '\ n' ile bitmezse yapılmalıdır.
Lennart Regebro

8
Eğer "\ n" ile biterse, son satır boş satırdır. Her ne kadar işe yaramaz olsa da, hala hat olarak sayılır, değil mi?
Jakub M.

2
Hayır. bir dosyaya 3 satır metin yazıp her birini satır besleme ile bitirdiğimde dosyanın 3 satır içerdiğini söyleyebilirim. unix'te bir metin dosyasının her zaman satır besleme ile bitmesi en iyi uygulamadır. Aksi takdirde cat filekomut satırınızı bozar ve yıkım şikayet eder. vi her zaman bir tane ekler.
user829755

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.

Son cümleyi not edin.

Satırları saymak için kaç tane olduğunu sayabilirsiniz \n:

line_count = some_string.count('\n') + some_string[-1] != '\n'

Son bölüm hesaba ile bitmez son satırı alır \nbile bu yollarla olsa Hello, World!ve Hello, World!\naksi eklemeniz yeterli, aynı hat sayısı (benim için makul olan) sahip 1sayımına \n.


0

Satırları saymak için satır sonlarını sayabilirsiniz:

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

Düzenle :

Yerleşik olan diğer cevapcount aslında daha uygundur


3
Sadece kullanmanın yanı sıra , booller counteklenebilir (aslında, alt sınıf int), bu yüzden genexp olarak yazılabilir sum(s == "\n" for s in the_string).
lvc

Şu anda sadece boş satırları mı sayıyorsunuz?
Thijs van Dien

Evet, boş satır
atmıyorum
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.