2009-03-17 10 views
2

J'écris une fonction Python pour diviser le texte en mots, en ignorant la ponctuation spécifiée. Voici un code de travail. Je ne suis pas convaincu que la construction de chaînes à partir de listes (buf = [] dans le code) est efficace. Quelqu'un at-il une suggestion pour une meilleure façon de faire cela?Un moyen efficace d'ajouter itérativement à une chaîne en Python?

def getwords(text, splitchars=' \t|!?.;:"'): 
    """ 
    Generator to get words in text by splitting text along specified splitchars 
    and stripping out the splitchars:: 

     >>> list(getwords('this is some text.')) 
     ['this', 'is', 'some', 'text'] 
     >>> list(getwords('and/or')) 
     ['and', 'or'] 
     >>> list(getwords('one||two')) 
     ['one', 'two'] 
     >>> list(getwords(u'hola unicode!')) 
     [u'hola', u'unicode'] 
    """ 
    splitchars = set(splitchars) 
    buf = [] 
    for char in text: 
     if char not in splitchars: 
      buf.append(char) 
     else: 
      if buf: 
       yield ''.join(buf) 
       buf = [] 
    # All done. Yield last word. 
    if buf: 
     yield ''.join(buf) 
+0

Dommage ... Donc, il y avait quelqu'un ici, qui a mis la meilleure réponse, en disant que le haut-scission a permis de mettre plus d'un splitChars. Vous avez dit que son code était moche, il a supprimé son message. – fulmicoton

Répondre

3

Vous pouvez utiliser re.split

re.split('[\s|!\?\.;:"]', text) 

Toutefois, si le texte est très volumineux, le tableau résultant peut consommer trop de mémoire. Ensuite, vous pouvez envisager re.finditer:

import re 
def getwords(text, splitchars=' \t|!?.;:"'): 
    words_iter = re.finditer(
    "([%s]+)" % "".join([("^" + c) for c in splitchars]), 
    text) 
    for word in words_iter: 
    yield word.group() 

# a quick test 
s = "a:b cc? def...a||" 
words = [x for x in getwords(s)] 
assert ["a", "b", "cc", "def", "a"] == words, words 
4

Vous ne souhaitez pas utiliser re.split?

import re 
re.split("[,; ]+", "coucou1 , coucou2;coucou3") 
+0

N'a pas pensé à ça du tout. Je vais le considérer. Merci! –

5

http://www.skymind.com/~ocrow/python_string/ parle de plusieurs façons de concaténer des chaînes en Python et évalue leur performance.

+0

C'était ce dont j'avais besoin. Merci. cStringIO apparaît comme le meilleur choix pour mon cas d'utilisation. –

+0

Euh oh. cStringIO ne peut pas gérer les chaînes Unicode. –

+0

Pour ce que ça vaut: j'ai piraté ce testcase jusqu'à ce qu'il fonctionne sur mon installation de Python 2.5, et j'ai trouvé la méthode 6 (feed '' .joindre une liste de compréhension) pour être toujours plus rapide. 6 avec les expressions de générateur s'est avéré * plus lent * mais toujours deuxième plus rapide. – kquinn

1

Vous pouvez diviser l'entrée en utilisant re.split():

>>> splitchars=' \t|!?.;:"' 
>>> re.split("[%s]" % splitchars, "one\ttwo|three?four") 
['one', 'two', 'three', 'four'] 
>>> 

EDIT: Si votre splitchars peut contenir des caractères spéciaux comme ] ou ^, vous pouvez utiliser re.escpae()

>>> re.escape(splitchars) 
'\\ \\\t\\|\\!\\?\\.\\;\\:\\"' 
>>> re.split("[%s]" % re.escape(splitchars), "one\ttwo|three?four") 
['one', 'two', 'three', 'four'] 
>>> 
Questions connexes