multiple into delimiters python string algorithm parsing split

into - Al dividir una cadena vacía en Python, ¿por qué split() devuelve una lista vacía mientras que split(''/ n'') devuelve['''']?



split python (6)

Estoy usando split(''/n'') para obtener líneas en una cadena, y encontré que ''''.split() devuelve una lista vacía, [] , mientras que ''''.split(''/n'') devuelve [''''] . ¿Hay alguna razón específica para tal diferencia?

¿Y hay alguna manera más conveniente de contar líneas en una cadena?


Pregunta: Estoy usando split (''/ n'') para obtener líneas en una cadena, y encontré que '''' .split () devuelve la lista vacía [], mientras que '''' .split (''/ n'') devuelve [''''] .

El método str.split() tiene dos algoritmos. Si no se dan argumentos, se divide en ejecuciones repetidas de espacios en blanco. Sin embargo, si se da un argumento, se trata como un delimitador único sin ejecuciones repetidas.

En el caso de dividir una cadena vacía, el primer modo (sin argumento) devolverá una lista vacía porque se consume el espacio en blanco y no hay valores para poner en la lista de resultados.

Por el contrario, el segundo modo (con un argumento como /n ) producirá el primer campo vacío. Considere si hubiera escrito ''/n''.split(''/n'') , obtendría dos campos (uno dividido, le da dos mitades).

Pregunta: ¿Hay alguna razón específica para tal diferencia?

Este primer modo es útil cuando los datos están alineados en columnas con cantidades variables de espacios en blanco. Por ejemplo:

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

El segundo modo es útil para datos delimitados, como CSV, donde las comas repetidas denotan campos vacíos. Por ejemplo:

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

Tenga en cuenta que el número de campos de resultados es uno mayor que el número de delimitadores. Piensa en cortar una cuerda. Si no haces cortes, tienes una pieza. Hacer un corte, da dos piezas. Hacer dos cortes, da tres piezas. Y lo mismo ocurre con el método str.split (delimitador) de Python:

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

Pregunta: ¿Y hay alguna manera más conveniente de contar líneas en una cadena?

Sí, hay un par de maneras fáciles. Uno usa str.count() y el otro usa str.splitlines() . Ambas formas darán la misma respuesta a menos que a la línea final le falte el /n . Si falta la última línea final, el enfoque str.splitlines dará la respuesta correcta. Una técnica más rápida que también es precisa utiliza el método de recuento pero luego lo corrige para la nueva línea final:

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

Pregunta de @Kaz: ¿Por qué diablos son dos algoritmos muy diferentes con cuernos de zapatos en una sola función?

La firma para str.split tiene aproximadamente 20 años, y varias de las API de esa época son estrictamente pragmáticas. Aunque no es perfecto, la firma del método tampoco es "terrible". En su mayor parte, las elecciones de diseño API de Guido han resistido la prueba del tiempo.

La API actual no está sin ventajas. Considere cadenas como:

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

Cuando se les pide que rompan estas cadenas en campos, las personas tienden a describir ambas usando la misma palabra en inglés, "dividir". Cuando se le pide que lea un código como fields = line.split() o fields = line.split('','') , las personas tienden a interpretar correctamente las declaraciones como "divide una línea en campos".

La herramienta de texto a columnas de Microsoft Excel hizo una elección de API similar e incorpora ambos algoritmos de división en la misma herramienta. La gente parece modelar mentalmente la división de campos como un concepto único a pesar de que se trata de más de un algoritmo.


Para contar líneas, puede contar la cantidad de saltos de línea:

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

Editar :

La otra respuesta con count incorporado es más adecuada, en realidad


Parece ser simplemente la forma en que debería funcionar, según la documentación :

La división de una cadena vacía con un separador especificado devuelve [''''] .

Si no se especifica sep o None, se aplicará un algoritmo de división diferente: las ejecuciones de espacios en blanco consecutivos se consideran como un único separador, y el resultado no contendrá cadenas vacías al inicio o al final si la cadena tiene espacios en blanco iniciales o finales. En consecuencia, dividir una cadena vacía o una cadena que consta de solo espacios en blanco con un separador Ninguno devuelve [].

Entonces, para hacerlo más claro, la función split() implementa dos algoritmos de división diferentes, y usa la presencia de un argumento para decidir cuál ejecutar. Esto podría ser porque permite optimizar el que no tiene más argumentos que el que tiene argumentos; No lo sé.


Use count() :

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


.split() sin parámetros intenta ser inteligente. Se divide en cualquier espacio en blanco, pestañas, espacios, líneas de alimentación, etc., y también omite todas las cadenas vacías como resultado de esto.

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

Básicamente, .split() sin parámetros se usa para extraer palabras de una cadena, en contraposición a .split() con parámetros que solo toman una cadena y la dividen.

Esa es la razón de la diferencia.

Y sí, contar líneas dividiendo no es una manera eficiente. Cuente el número de alimentaciones de línea y agregue una si la cadena no finaliza con un avance de línea.


>>> 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.

Tenga en cuenta la última oración.

Para contar líneas, simplemente puedes contar cuántos /n hay:

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

La última parte tiene en cuenta la última línea que no termina con /n , aunque esto significa que Hello, World! y Hello, World!/n tienen el mismo recuento de líneas (que para mí es razonable), de lo contrario, simplemente puede agregar 1 al recuento de /n .