2009-03-17 9 views
2

Ich schreibe eine Python-Funktion, um Text in Wörter zu teilen und angegebene Interpunktion zu ignorieren. Hier ist ein funktionierender Code. Ich bin nicht davon überzeugt, dass das Konstruieren von Strings aus Listen (buf = [] im Code) effizient ist. Hat jemand einen Vorschlag für einen besseren Weg?Effektiver Weg, um eine Zeichenfolge in Python iterativ anzuhängen?

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

Schade ... Also hier war jemand, der die beste Antwort gab und sagte, dass der eingebaute Splitter mehr als einen Splitchar setzen konnte. Sie sagten, sein Code sei hässlich, er löschte seine Nachricht. – fulmicoton

Antwort

3

Sie können re.split verwenden verwenden

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

Wenn der Text jedoch sehr groß ist, verbraucht das resultierende Array möglicherweise zu viel Speicher. Dann kannst du re.finditer betrachten:

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

Sie möchten re.split nicht verwenden?

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

Daran habe ich überhaupt nicht gedacht. Wird es in Betracht ziehen. Vielen Dank! –

5

http://www.skymind.com/~ocrow/python_string/ spricht über verschiedene Möglichkeiten von Strings in Python verketten und bewertet sowie deren Leistung.

+0

Das war was ich brauchte. Vielen Dank. cStringIO erscheint die beste Wahl für meinen Anwendungsfall. –

+0

Uh oh. cStringIO kann Unicode-Zeichenfolgen nicht verarbeiten. –

+0

Für was es wert ist: Ich habe diesen Testfall gehackt, bis er auf meiner Python 2.5-Installation lief, und fand Methode 6 (feed '' .join a list comprehension) konstant schnell zu sein. 6 mit Generator-Ausdrücken erwies sich als * langsamer * aber immer noch am zweitschnellsten. – kquinn

1

Sie können die Eingabe geteilt mit re.split():

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

EDIT: Wenn Ihr splitchars Sonderzeichen wie ] oder ^ enthalten können, können Sie re.escpae()

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