Dlaczego podczas dzielenia pustego ciągu w Pythonie split () zwraca pustą listę, podczas gdy split ('\ n') zwraca ['']?
155
Używam, split('\n')aby uzyskać wiersze w jednym ciągu i okazało się, że ''.split()zwraca pustą listę [], a ''.split('\n')zwraca ['']. Czy jest jakiś konkretny powód takiej różnicy?
Czy istnieje wygodniejszy sposób liczenia wierszy w ciągu?
Pytanie: Używam split ('\ n'), aby uzyskać wiersze w jednym ciągu i stwierdziłem, że '' .split () zwraca pustą listę [], podczas gdy '' .split ('\ n') zwraca [''] .
Metoda str.split () ma dwa algorytmy. Jeśli nie podano żadnych argumentów, dzieli się na powtarzające się ciągi białych znaków. Jeśli jednak podano argument, jest on traktowany jako pojedynczy ogranicznik bez powtarzających się przebiegów.
W przypadku dzielenia pustego łańcucha, pierwszy tryb (bez argumentu) zwróci pustą listę, ponieważ biały znak jest zjadany i nie ma żadnych wartości do umieszczenia na liście wyników.
Natomiast drugi tryb (z argumentem takim jak \n) da pierwsze puste pole. Zastanów się, czy napisałeś '\n'.split('\n'), dostałbyś dwa pola (jeden podział daje dwie połowy).
Pytanie: Czy jest jakiś konkretny powód takiej różnicy?
Ten pierwszy tryb jest przydatny, gdy dane są wyrównane w kolumnach ze zmiennymi ilościami białych znaków. Na przykład:
>>> 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']
Drugi tryb jest przydatny w przypadku danych rozdzielanych, takich jak CSV, gdzie powtarzające się przecinki oznaczają puste pola. Na przykład:
>>> 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']
Zauważ, że liczba pól wynikowych jest o jeden większa niż liczba ograniczników. Pomyśl o przecięciu liny. Jeśli nie wykonasz żadnych cięć, masz jeden kawałek. Wykonanie jednego cięcia daje dwie sztuki. Wykonanie dwóch cięć daje trzy sztuki. I tak jest z metodą str.split (delimiter) Pythona :
>>>''.split(',')# No cuts['']>>>','.split(',')# One cut['','']>>>',,'.split(',')# Two cuts['','','']
Pytanie: Czy istnieje wygodniejszy sposób liczenia wierszy w ciągu?
Tak, jest kilka łatwych sposobów. Jedna używa str.count (), a druga używa str.splitlines () . Oba sposoby dadzą tę samą odpowiedź, chyba że w ostatnim wierszu brakuje \n. Jeśli brakuje ostatniej nowej linii, podejście str.splitlines da dokładną odpowiedź. Szybsza technika, która jest również dokładna, wykorzystuje metodę zliczania, ale następnie koryguje ją pod kątem końcowego znaku nowej linii:
>>> data ='''\
Line 1
Line 2
Line 3
Line 4'''>>> data.count('\n')# Inaccurate3>>> len(data.splitlines())# Accurate, but slow4>>> data.count('\n')+(not data.endswith('\n'))# Accurate and fast4
Pytanie od @Kaz: Dlaczego do cholery są dwa bardzo różne algorytmy połączone w jedną funkcję?
Podpis dla str.split ma około 20 lat, a wiele interfejsów API z tamtej epoki jest ściśle pragmatycznych. Chociaż nie jest doskonały, sygnatura metody nie jest też „straszna”. W większości wybory projektowe API Guido przetrwały próbę czasu.
Obecne API nie jest pozbawione zalet. Rozważ ciągi, takie jak:
Poproszeni o podzielenie tych ciągów na pola, ludzie mają tendencję do opisywania obu za pomocą tego samego angielskiego słowa „podziel”. Poproszeni o odczytanie kodu, takiego jak fields = line.split()
lub fields = line.split(','), ludzie mają tendencję do poprawnej interpretacji instrukcji jako „dzielenia wiersza na pola”.
Narzędzie zamiany tekstu na kolumny programu Microsoft Excel dokonało podobnego wyboru interfejsu API i zawiera oba algorytmy dzielenia w tym samym narzędziu. Wydaje się, że ludzie modelują w myślach podział pól jako jedną koncepcję, mimo że w grę wchodzi więcej niż jeden algorytm.
Wygląda na to, że po prostu ma działać, zgodnie z dokumentacją :
Dzielenie pustego ciągu z określonym separatorem zwraca [''].
Jeśli sep nie jest określony lub ma wartość None, stosowany jest inny algorytm podziału: ciągi kolejnych białych znaków są traktowane jako pojedynczy separator, a wynik nie będzie zawierał pustych ciągów na początku lub na końcu, jeśli łańcuch ma początkowe lub końcowe białe spacje. W konsekwencji dzielenie pustego łańcucha lub łańcucha składającego się tylko z białych znaków z separatorem None zwraca [].
Tak więc, aby było jaśniej, split()funkcja implementuje dwa różne algorytmy dzielenia i wykorzystuje obecność argumentu, aby zdecydować, który z nich uruchomić. Może to być spowodowane tym, że pozwala zoptymalizować ten, który nie zawiera argumentów więcej niż ten z argumentami; Nie wiem
.split()bez parametrów stara się być sprytny. Dzieli się na dowolne białe spacje, tabulatory, spacje, nowe wiersze itp., A także w wyniku tego pomija wszystkie puste ciągi.
Zasadniczo .split()bez parametrów są używane do wyodrębniania słów z ciągu, w przeciwieństwie do .split()parametrów, które po prostu pobierają ciąg i dzielą go.
To jest powód tej różnicy.
I tak, liczenie linii przez dzielenie nie jest wydajnym sposobem. Policz liczbę wysuwów wiersza i dodaj jeden, jeśli ciąg nie kończy się wysuwem wiersza.
+ 1 należy wykonać tylko wtedy, gdy tekst nie kończy się na „\ n”.
Lennart Regebro
8
Cóż, jeśli kończy się na „\ n”, ostatnia linia jest pusta. Chociaż bezużyteczne, nadal liczy się jako linia, prawda?
Jakub M.
2
Nie. kiedy piszę 3 linie tekstu do pliku i kończę każdy z nich znakiem nowej linii, wtedy powiedziałbym, że plik zawiera 3 linie. w systemie UNIX najlepszą praktyką jest, aby plik tekstowy zawsze kończył się znakiem nowej linii. w przeciwnym razie cat filezniekształca linię poleceń i narzeka subversion. vi zawsze dołącza jeden.
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 isnot specified orisNone, any
whitespace string is a separator and empty strings are removed
from the result.
Zwróć uwagę na ostatnie zdanie.
Aby policzyć linie, możesz po prostu policzyć, ile \nich jest:
Ostatnia część bierze pod uwagę ostatnią linię, która nie kończy się na \n, mimo że oznacza to Hello, World!i Hello, World!\nmają taką samą liczbę linii (co dla mnie jest rozsądne), w przeciwnym razie możesz po prostu dodać 1do liczby \n.
Odpowiedzi:
Metoda str.split () ma dwa algorytmy. Jeśli nie podano żadnych argumentów, dzieli się na powtarzające się ciągi białych znaków. Jeśli jednak podano argument, jest on traktowany jako pojedynczy ogranicznik bez powtarzających się przebiegów.
W przypadku dzielenia pustego łańcucha, pierwszy tryb (bez argumentu) zwróci pustą listę, ponieważ biały znak jest zjadany i nie ma żadnych wartości do umieszczenia na liście wyników.
Natomiast drugi tryb (z argumentem takim jak
\n
) da pierwsze puste pole. Zastanów się, czy napisałeś'\n'.split('\n')
, dostałbyś dwa pola (jeden podział daje dwie połowy).Ten pierwszy tryb jest przydatny, gdy dane są wyrównane w kolumnach ze zmiennymi ilościami białych znaków. Na przykład:
Drugi tryb jest przydatny w przypadku danych rozdzielanych, takich jak CSV, gdzie powtarzające się przecinki oznaczają puste pola. Na przykład:
Zauważ, że liczba pól wynikowych jest o jeden większa niż liczba ograniczników. Pomyśl o przecięciu liny. Jeśli nie wykonasz żadnych cięć, masz jeden kawałek. Wykonanie jednego cięcia daje dwie sztuki. Wykonanie dwóch cięć daje trzy sztuki. I tak jest z metodą str.split (delimiter) Pythona :
Tak, jest kilka łatwych sposobów. Jedna używa str.count (), a druga używa str.splitlines () . Oba sposoby dadzą tę samą odpowiedź, chyba że w ostatnim wierszu brakuje
\n
. Jeśli brakuje ostatniej nowej linii, podejście str.splitlines da dokładną odpowiedź. Szybsza technika, która jest również dokładna, wykorzystuje metodę zliczania, ale następnie koryguje ją pod kątem końcowego znaku nowej linii:Podpis dla str.split ma około 20 lat, a wiele interfejsów API z tamtej epoki jest ściśle pragmatycznych. Chociaż nie jest doskonały, sygnatura metody nie jest też „straszna”. W większości wybory projektowe API Guido przetrwały próbę czasu.
Obecne API nie jest pozbawione zalet. Rozważ ciągi, takie jak:
Poproszeni o podzielenie tych ciągów na pola, ludzie mają tendencję do opisywania obu za pomocą tego samego angielskiego słowa „podziel”. Poproszeni o odczytanie kodu, takiego jak
fields = line.split()
lubfields = line.split(',')
, ludzie mają tendencję do poprawnej interpretacji instrukcji jako „dzielenia wiersza na pola”.Narzędzie zamiany tekstu na kolumny programu Microsoft Excel dokonało podobnego wyboru interfejsu API i zawiera oba algorytmy dzielenia w tym samym narzędziu. Wydaje się, że ludzie modelują w myślach podział pól jako jedną koncepcję, mimo że w grę wchodzi więcej niż jeden algorytm.
źródło
Wygląda na to, że po prostu ma działać, zgodnie z dokumentacją :
Tak więc, aby było jaśniej,
split()
funkcja implementuje dwa różne algorytmy dzielenia i wykorzystuje obecność argumentu, aby zdecydować, który z nich uruchomić. Może to być spowodowane tym, że pozwala zoptymalizować ten, który nie zawiera argumentów więcej niż ten z argumentami; Nie wiemźródło
.split()
bez parametrów stara się być sprytny. Dzieli się na dowolne białe spacje, tabulatory, spacje, nowe wiersze itp., A także w wyniku tego pomija wszystkie puste ciągi.Zasadniczo
.split()
bez parametrów są używane do wyodrębniania słów z ciągu, w przeciwieństwie do.split()
parametrów, które po prostu pobierają ciąg i dzielą go.To jest powód tej różnicy.
I tak, liczenie linii przez dzielenie nie jest wydajnym sposobem. Policz liczbę wysuwów wiersza i dodaj jeden, jeśli ciąg nie kończy się wysuwem wiersza.
źródło
Zastosowanie
count()
:źródło
cat file
zniekształca linię poleceń i narzeka subversion. vi zawsze dołącza jeden.Zwróć uwagę na ostatnie zdanie.
Aby policzyć linie, możesz po prostu policzyć, ile
\n
ich jest:Ostatnia część bierze pod uwagę ostatnią linię, która nie kończy się na
\n
, mimo że oznacza toHello, World!
iHello, World!\n
mają taką samą liczbę linii (co dla mnie jest rozsądne), w przeciwnym razie możesz po prostu dodać1
do liczby\n
.źródło
Aby policzyć wiersze, możesz policzyć podziały wierszy:
Edycja :
count
Właściwie druga odpowiedź z wbudowanym jest bardziej odpowiedniaźródło
count
, bools są dodawane (w rzeczywistości są podklasąint
), więc genexp można zapisać jakosum(s == "\n" for s in the_string)
.