2012-03-21 10 views
5

Estoy tratando de dividir una cadena en palabras, eliminando espacios y signos de puntuación.División de una cadena en varios signos de puntuación mediante división()

He intentado utilizar el método split(), pasando toda la puntuacion a la vez, pero mis resultados no son correctos:

>>> test='hello,how are you?I am fine,thank you. And you?' 
>>> test.split(' ,.?') 
['hello,how are you?I am fine,thank you. And you?'] 

que realmente saben cómo hacer esto con expresiones regulares ya, pero me gustaría averiguar cómo hacerlo usando split(). Por favor no me des una solución de expresiones regulares.

+2

Así que insiste en usar una llave para clavar un clavo, mientras que el martillo está a mano. ¿Por qué? –

+0

Sin que signifique ninguna falta de respeto al OP Creo que debería haber una etiqueta para este tipo de preguntas en la cual la herramienta adecuada es desairada por cualquier razón (a veces válida), que aparece de vez en cuando. Tal vez 'luddism'? –

+0

prueba C# "hola, ¿cómo estás? Estoy bien, gracias. ¿Y tú?". Split (",?.". ToCharArray(), StringSplitOptions.RemoveEmptyEntries); –

Respuesta

10

Esta es la mejor manera que puedo pensar sin utilizar el módulo re:

"".join((char if char.isalpha() else " ") for char in test).split() 
+0

Ooo, esa es otra forma de hacerlo, aunque no utiliza la lista explícita de caracteres divididos ... – larsks

+0

su código es mejor, puede manejar otros signos de puntuación – leisurem

+0

Esto es genial. Aunque es un poco menos eficiente en comparación con el uso de re.split. –

11

Si desea dividir una cadena basada en múltiples delimitadores, como en el ejemplo, se van a necesitar utilizar el módulo re a pesar de sus objeciones extrañas, como esto:

>>> re.split('[?.,]', test) 
['hello', 'how are you', 'I am fine', 'thank you', ' And you', ''] 

¡Es posible para obtener un resultado similar usando split, pero debe llamar a dividir una vez para cada carácter, y debe iterar sobre los resultados de la división anterior. Esto funciona, pero es u-g-l-Y:

>>> sum([z.split() 
... for z in sum([y.split('?') 
... for y in sum([x.split('.') 
... for x in test.split(',')],[])], [])], []) 
['hello', 'how', 'are', 'you', 'I', 'am', 'fine', 'thank', 'you', 'And', 'you'] 

Este utiliza sum() para aplanar la lista devuelta por la iteración anterior.

+0

No use 'suma()' para aplanar listas de listas - [es la herramienta incorrecta para este propósito] (http://stackoverflow.com/questions/952914/making-a-flat-list-out- of-list-of-lists-in-python/952952 # 952952). En este caso particular, aún más, ya que una [comprensión de lista única usando un bucle anidado] (http://ideone.com/xEXX7) eliminaría la necesidad de aplanar en primer lugar. –

+0

Puede enviar una solución alternativa si cree que es más adecuada para el problema. – larsks

+0

Mientras el OP no explique por qué 're' no se debe utilizar, no publicaré una respuesta, ya que aún no entiendo el motivo de la pregunta. El segundo enlace en mi último comentario muestra una solución alternativa, sin embargo. –

6

Puesto que usted no desea utilizar el módulo de regreso, puede utilizar esto:

test.replace(',',' ').replace('.',' ').replace('?',' ').split() 
+0

test = 'hola, ¿cómo estás? Estoy bien, gracias. ¿Y tu?' para x en la prueba: si no x.isalpha(): test = test.replace (x,' ') test = test.split() prueba de impresión – leisurem

3

puede escribir una función para extender el uso de .split():

def multi_split(s, seprators): 
    buf = [s] 
    for sep in seprators: 
     for loop, text in enumerate(buf): 
      buf[loop:loop+1] = [i for i in text.split(sep) if i] 
    return buf 

y probarlo:

>>> multi_split('hello,how are you?I am fine,thank you. And you?', ' ,.?') ['hello', 'how', 'are', 'you', 'I', 'am', 'fine', 'thank', 'you', 'And', 'you']

Esto será más clara y se puede utilizar en otras situaciones.

3

Una versión modificada de respuesta larsks', en el que no tiene que escribir todos los caracteres de puntuación a sí mismo:

import re, string 

re.split("[" + string.punctuation + "]+", test) 
['hello', 'how are you', 'I am fine', 'thank you', ' And you', ''] 
0

Disculpas por necroing - este hilo aparece como primer resultado de la división de expresiones regulares no una sentencia. Al ver que tenía que idear un método que no sea específico de Python para mis alumnos, y que este hilo no respondía a mi pregunta, pensé que podría compartirlo por si acaso.

El punto de código es utilizar ninguna biblioteca (y es rápido en archivos de gran tamaño):

sentence = "George Bernard-Shaw was a fine chap, I'm sure - who can really say?" 
alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 
words = [] 
word = "" 
mode = 0 
for ch in sentence: 
    if mode == 1: 
     words.append(word) 
     word = "" 
     mode = 0 
    if ch in alpha or ch == "'" or ch == "-": 
     word += ch 
    else: 
     mode = 1 
words.append(word) 
print(words) 

Salida:

['George', 'Bernard-Shaw', 'was', 'a', 'fine', 'chap', "I'm", 'sure', '-', 'who', 'can', 'really', 'say'] 

he literalmente, acaba de escribir esto en aproximadamente media hora así que estoy seguro de que la lógica podría ser limpiada.También he reconocido que puede requerir lógica adicional para tratar con advertencias, como guiones, correctamente, ya que su uso es inconsistente en comparación con algo así como una coma invertida. ¿Hay algún módulo, de hecho, que pueda hacer esto correctamente de todos modos?