it-swarm.com.de

Teilen Sie Strings in Wörter mit mehreren Begrenzungszeichen für Wortbegrenzungen

Ich denke, was ich tun möchte, ist eine ziemlich gewöhnliche Aufgabe, aber ich habe im Web keinen Hinweis gefunden. Ich habe Text mit Interpunktion und möchte eine Liste der Wörter. 

"Hey, you - what are you doing here!?"

sollte sein

['hey', 'you', 'what', 'are', 'you', 'doing', 'here']

Aber Pythons str.split() funktioniert nur mit einem Argument, also habe ich alle Wörter mit der Interpunktion, nachdem ich mich mit Leerzeichen getrennt habe. Irgendwelche Ideen?

565
ooboo

Ein Fall, in dem reguläre Ausdrücke berechtigt sind:

import re
DATA = "Hey, you - what are you doing here!?"
print re.findall(r"[\w']+", DATA)
# Prints ['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']
396
RichieHindle

re.split ()

re.split (pattern, string [ maxsplit = 0])

Zeichenfolge nach Vorkommen von Muster aufteilen. Wenn in pattern Capturing-Klammern verwendet werden, wird der Text aller Gruppen im Pattern ebenfalls als Teil der Ergebnisliste zurückgegeben. Wenn maxsplit ungleich Null ist, treten höchstens maxsplit-Aufteilungen auf, und der Rest der Zeichenfolge wird als das letzte Element der Liste zurückgegeben. (Hinweis zur Inkompatibilität: In der ursprünglichen Version von Python 1.5 wurde maxsplit ignoriert. Dies wurde in späteren Versionen behoben.)

>>> re.split('\W+', 'Words, words, words.')
['Words', 'words', 'words', '']
>>> re.split('(\W+)', 'Words, words, words.')
['Words', ', ', 'words', ', ', 'words', '.', '']
>>> re.split('\W+', 'Words, words, words.', 1)
['Words', 'words, words.']
471
gimel

Eine weitere Möglichkeit, dies ohne einen regulären Ausdruck zu erreichen, besteht darin, die Zeichen zuerst wie folgt zu ersetzen:

>>> 'a;bcd,ef g'.replace(';',' ').replace(',',' ').split()
['a', 'bcd', 'ef', 'g']
308
Louis LC

So viele Antworten, aber ich kann keine Lösung finden, die effizient das tut, was der title der Fragen buchstäblich verlangt (Aufteilung in mehrere mögliche Trennzeichen) - stattdessen entfernen viele Antworten alles, was kein Wort ist, das anders ist ). Hier ist also eine Antwort auf die Frage im Titel, die auf Pythons Standard- und effizientem re-Modul basiert:

>>> import re  # Will be splitting on: , <space> - ! ? :
>>> filter(None, re.split("[, \-!?:]+", "Hey, you - what are you doing here!?"))
['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']

woher:

  • der […] stimmt mit one der darin aufgeführten Trennzeichen überein,
  • der \- im regulären Ausdruck soll hier die spezielle Interpretation von - als Zeichen für den Zeichenbereich (wie in A-Z) verhindern.
  • der + überspringt ein oder mehrere Trennzeichen (es könnte dank filter() weggelassen werden, dies würde jedoch unnötigerweise leere Zeichenfolgen zwischen übereinstimmenden Trennzeichen erzeugen) und
  • filter(None, …) entfernt die leeren Zeichenfolgen, die möglicherweise von führenden und nachgestellten Trennzeichen erstellt wurden (da leere Zeichenfolgen einen falschen booleschen Wert haben).

Diese re.split() "teilt sich genau mit mehreren Trennzeichen auf", wie im Fragentitel verlangt.

Diese Lösung ist außerdem immun gegen die Probleme mit Nicht-ASCII-Zeichen in Wörtern, die in einigen anderen Lösungen gefunden wurden (siehe den ersten Kommentar zu ghostdog74s Antwort ).

Das re-Modul ist (in Geschwindigkeit und Präzision) wesentlich effizienter als Python-Loops und Tests "von Hand"!

244
Eric O Lebigot

Ein anderer Weg, ohne Regex

import string
punc = string.punctuation
thestring = "Hey, you - what are you doing here!?"
s = list(thestring)
''.join([o for o in s if not o in punc]).split()
53
ghostdog74

Pro-Tipp: Verwenden Sie string.translate für die schnellsten Zeichenfolgenoperationen, die Python ausführt.

Einige Beweise ...

Zuerst der langsame Weg (sorry pprzemek):

>>> import timeit
>>> S = 'Hey, you - what are you doing here!?'
>>> def my_split(s, seps):
...     res = [s]
...     for sep in seps:
...         s, res = res, []
...         for seq in s:
...             res += seq.split(sep)
...     return res
... 
>>> timeit.Timer('my_split(S, punctuation)', 'from __main__ import S,my_split; from string import punctuation').timeit()
54.65477919578552

Als Nächstes verwenden wir re.findall() (wie in der vorgeschlagenen Antwort angegeben). Viel schneller:

>>> timeit.Timer('findall(r"\w+", S)', 'from __main__ import S; from re import findall').timeit()
4.194725036621094

Zum Schluss verwenden wir translate:

>>> from string import translate,maketrans,punctuation 
>>> T = maketrans(punctuation, ' '*len(punctuation))
>>> timeit.Timer('translate(S, T).split()', 'from __main__ import S,T,translate').timeit()
1.2835021018981934

Erklärung:

string.translate ist in C implementiert und im Gegensatz zu vielen Zeichenfolgenbearbeitungsfunktionen in Python erzeugt string.translate nicht eine neue Zeichenfolge. Es ist also ungefähr so ​​schnell wie möglich, um die Saite zu ersetzen.

Es ist jedoch etwas umständlich, da es eine Übersetzungstabelle benötigt, um diese Magie auszuführen. Sie können mit der Komfortfunktion maketrans() eine Übersetzungstabelle erstellen. Ziel ist es, alle unerwünschten Zeichen in Leerzeichen zu übersetzen. Ein Eins-zu-Eins-Stellvertreter. Wieder werden keine neuen Daten erzeugt. Das ist also schnell !

Als nächstes verwenden wir gutes altes split(). split() wirkt standardmäßig auf alle Leerzeichen und gruppiert sie für den Split. Das Ergebnis ist die Liste der gewünschten Wörter. Und dieser Ansatz ist fast 4x schneller als re.findall()!

36
Dave

Irgendwie eine späte Antwort :), aber ich hatte ein ähnliches Dilemma und wollte kein re-Modul verwenden.

def my_split(s, seps):
    res = [s]
    for sep in seps:
        s, res = res, []
        for seq in s:
            res += seq.split(sep)
    return res

print my_split('1111  2222 3333;4444,5555;6666', [' ', ';', ','])
['1111', '', '2222', '3333', '4444', '5555', '6666']
22
pprzemek
join = lambda x: sum(x,[])  # a.k.a. flatten1([[1],[2,3],[4]]) -> [1,2,3,4]
# ...alternatively...
join = lambda lists: [x for l in lists for x in l]

Dann wird dies ein Drei-Liner:

fragments = [text]
for token in tokens:
    fragments = join(f.split(token) for f in fragments)

Erklärung

Dies ist, was in Haskell als Listenmonad bekannt ist. Die Idee hinter der Monade ist, dass Sie einmal "in der Monade" "in der Monade bleiben", bis Sie etwas herausholt. Zum Beispiel sagen Sie in Haskell, dass Sie die Python-Funktion range(n) -> [1,2,...,n] einer Liste zuordnen. Wenn das Ergebnis eine Liste ist, wird diese an die vorhandene Liste angehängt, so dass Sie etwas wie map(range, [3,4,1]) -> [0,1,2,0,1,2,3,0] erhalten. Dies wird als map-append (oder mappend oder vielleicht so ähnlich) bezeichnet. Die Idee hier ist, dass Sie diese Operation haben, die Sie anwenden (Aufteilen eines Tokens), und wenn Sie dies tun, fügen Sie das Ergebnis in die Liste ein.

Sie können dies in eine Funktion abstrahieren und standardmäßig tokens=string.punctuation verwenden. 

Vorteile dieses Ansatzes:

  • Dieser Ansatz kann (im Gegensatz zu naiven regex-basierten Ansätzen) mit Token mit beliebiger Länge arbeiten (was mit regulärem Ausdruck auch mit einer fortgeschritteneren Syntax möglich ist).
  • Sie sind nicht nur auf Spielmarken beschränkt. Sie könnten eine beliebige Logik anstelle jedes Tokens verwenden, zum Beispiel könnte einer der "Tokens" eine Funktion sein, die sich nach geschachtelten Klammern aufteilt.
10
ninjagecko

Erstens möchte ich anderen zustimmen, dass die auf Regex oder str.translate(...) basierenden Lösungen am leistungsfähigsten sind. Für meinen Anwendungsfall war die Leistung dieser Funktion nicht signifikant, daher wollte ich Ideen hinzufügen, die ich mit diesen Kriterien berücksichtigte.

Mein Hauptziel war es, Ideen aus einigen der anderen Antworten in einer Lösung zu verallgemeinern, die für Zeichenfolgen funktionieren könnte, die mehr als nur reguläre Wörter enthalten (d. H. Die explizite Untergruppe von Interpunktionszeichen auf eine schwarze Liste setzen und Wortzeichen auf eine weiße Liste setzen).

Beachten Sie, dass Sie in jedem Fall in Betracht ziehen könnten, string.punctuation Anstelle einer manuell definierten Liste zu verwenden.

Option 1 - re

Ich war überrascht zu sehen, dass bisher keine Antwort re (...) verwendet. Ich finde es eine einfache und natürliche Herangehensweise an dieses Problem.

import re

my_str = "Hey, you - what are you doing here!?"

words = re.split(r'\s+', re.sub(r'[,\-!?]', ' ', my_str).strip())

In dieser Lösung habe ich den Aufruf von re.sub(...) inside re.split(...) verschachtelt. Wenn die Leistung jedoch kritisch ist, kann das Kompilieren der Regex outside von Vorteil sein. Für meinen Anwendungsfall war der Unterschied nicht signifikant Ich bevorzuge daher Einfachheit und Lesbarkeit.

Option 2 - Austausch

Das sind noch ein paar Zeilen, aber es hat den Vorteil, dass es erweiterbar ist, ohne dass Sie prüfen müssen, ob Sie einem bestimmten Zeichen in Regex entkommen müssen.

my_str = "Hey, you - what are you doing here!?"

replacements = (',', '-', '!', '?')
for r in replacements:
    my_str = my_str.replace(r, ' ')

words = my_str.split()

Es wäre schön gewesen, wenn Sie stattdessen die Zeichenfolge auf die Zeichenfolge abbilden könnten, aber ich glaube nicht, dass dies mit unveränderlichen Zeichenfolgen möglich wäre, und wenn die Zuordnung anhand einer Liste von Zeichen funktionieren würde, würde jede Ersetzung für jedes Zeichen ausgeführt klingt übertrieben. (Bearbeiten: Ein Funktionsbeispiel finden Sie in der nächsten Option.)

Option 3 - functools.reduce

(In Python 2, reduce ist im globalen Namespace verfügbar, ohne ihn aus Funktools zu importieren.)

import functools

my_str = "Hey, you - what are you doing here!?"

replacements = (',', '-', '!', '?')
my_str = functools.reduce(lambda s, sep: s.replace(sep, ' '), replacements, my_str)
words = my_str.split()
10
Taylor Edmiston

versuche dies:

import re

phrase = "Hey, you - what are you doing here!?"
matches = re.findall('\w+', phrase)
print matches

dies wird ['Hey', 'you', 'what', 'are', 'you', 'doing', 'here'] drucken

4
Corey Goldberg

Verwenden Sie zweimal ersetzen:

a = '11223FROM33344INTO33222FROM3344'
a.replace('FROM', ',,,').replace('INTO', ',,,').split(',,,')

ergebnisse in: 

['11223', '33344', '33222', '3344']
4
jeroen

Ich mag re, aber hier ist meine Lösung ohne:

from itertools import groupby
sep = ' ,-!?'
s = "Hey, you - what are you doing here!?"
print [''.join(g) for k, g in groupby(s, sep.__contains__) if not k]

sep .__ contains__ ist eine Methode, die vom Operator 'in' verwendet wird. Im Grunde ist es das Gleiche wie

lambda ch: ch in sep

ist aber hier bequemer.

groupby erhält unsere Zeichenfolge und Funktion. Mit dieser Funktion wird der String in Gruppen aufgeteilt: Immer wenn sich ein Funktionswert ändert, wird eine neue Gruppe generiert. Also ist sep .__ contains__ genau das, was wir brauchen.

groupby liefert eine Folge von Paaren, wobei Paar [0] ein Ergebnis unserer Funktion und Paar [1] eine Gruppe ist. Mit 'if not k' filtern wir Gruppen mit Trennzeichen heraus (weil ein Ergebnis von sep .__ enthält__ auf Trennzeichen True ist). Nun, das ist alles - jetzt haben wir eine Sequenz von Gruppen, in denen jede ein Wort ist (die Gruppe ist eigentlich eine Iteration, also verwenden wir join, um es in einen String zu konvertieren).

Diese Lösung ist ziemlich allgemein, da sie eine Funktion zum Trennen der Zeichenfolge verwendet (Sie können nach jeder gewünschten Bedingung aufteilen). Außerdem werden keine Zwischenfolgen/Listen erstellt (Sie können join entfernen und der Ausdruck wird faul, da jede Gruppe ein Iterator ist.)

4
monitorius

Anstelle der re-Modul-Funktion re.split können Sie dasselbe Ergebnis mit der series.str.split-Methode von Pandas erzielen. 

Erstellen Sie zuerst eine Reihe mit der obigen Zeichenfolge und wenden Sie dann die Methode auf die Reihe an.

thestring = pd.Series("Hey, you - what are you doing here!?") thestring.str.split(pat = ',|-')

der Parameter pat übernimmt die Trennzeichen und gibt den Split-String als Array zurück. Hier werden die beiden Trennzeichen mit einem | übergeben (oder Operator) ..__ Die Ausgabe lautet wie folgt:

[Hey, you , what are you doing here!?]  

3

Ich kenne mich wieder mit Python und brauchte dasselbe ... Die Findall-Lösung ist vielleicht besser, aber ich habe mir Folgendes ausgedacht:

tokens = [x.strip() for x in data.split(',')]
3
Leon Starr

In Python 3 können Sie die Methode von PY4E - Python für alle verwenden.

Wir können beide Probleme mit den String-Methoden lower, punctuation und translate lösen. Die translate ist die subtilste der Methoden. Hier ist die Dokumentation für translate:

your_string.translate(your_string.maketrans(fromstr, tostr, deletestr))

Ersetzen Sie die Zeichen in fromstr durch die Zeichen an derselben Position in tostr und löschen Sie alle Zeichen in deletestr. Die Zeichenfolgen fromstr und tostr können leer sein, und der Parameter deletestr kann weggelassen werden.

Sie können die "Interpunktion" sehen:

In [10]: import string

In [11]: string.punctuation
Out[11]: '!"#$%&\'()*+,-./:;<=>[email protected][\\]^_`{|}~'  

Für Ihr Beispiel:

In [12]: your_str = "Hey, you - what are you doing here!?"

In [13]: line = your_str.translate(your_str.maketrans('', '', string.punctuation))

In [14]: line = line.lower()

In [15]: words = line.split()

In [16]: print(words)
['hey', 'you', 'what', 'are', 'you', 'doing', 'here']

Weitere Informationen erhalten Sie unter:

3
Jeremy Anifacc

Erstellen Sie eine Funktion, die als Eingabe zwei Zeichenfolgen (die zu teilende Quellzeichenfolge und die Trennlistenzeichenfolge der Trennzeichen) als Eingabe übernimmt und eine Liste der Teilwörter ausgibt:

def split_string(source, splitlist):
    output = []  # output list of cleaned words
    atsplit = True
    for char in source:
        if char in splitlist:
            atsplit = True
        else:
            if atsplit:
                output.append(char)  # append new Word after split
                atsplit = False
            else: 
                output[-1] = output[-1] + char  # continue copying characters until next split
    return output
1
user852006

Eine andere Möglichkeit, dies zu erreichen, ist die Verwendung des Natural Language Tool Kit ( nltk ).

import nltk
data= "Hey, you - what are you doing here!?"
Word_tokens = nltk.tokenize.regexp_tokenize(data, r'\w+')
print Word_tokens

Dies druckt: ['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']

Der größte Nachteil dieser Methode ist, dass Sie das nltk-Paket installieren müssen.

Die Vorteile sind, dass Sie viele lustige Sachen mit dem Rest des nltk-Pakets machen können, sobald Sie Ihre Token erhalten.

1
tgray

Verwenden Sie immer re.compile (), bevor Sie einen RegEx-Vorgang in einer Schleife ausführen, da er schneller arbeitet als der normale Betrieb.

kompilieren Sie daher für Ihr Problem zuerst das Muster und führen Sie dann eine Aktion aus.

import re
DATA = "Hey, you - what are you doing here!?"
reg_tok = re.compile("[\w']+")
print reg_tok.findall(DATA)
1
shrikant

Zunächst einmal glaube ich nicht, dass Sie Interpunktion tatsächlich als Trennzeichen in den Split-Funktionen verwenden möchten. Ihre Beschreibung legt nahe, dass Sie einfach Interpunktion aus den resultierenden Zeichenfolgen entfernen möchten.

Ich stelle das ziemlich häufig fest und meine gewöhnliche Lösung erfordert keine erneute Lösung.

Einliner-Lambda-Funktion mit Listenverständnis:

(erfordert import string):

split_without_punc = lambda text : [Word.strip(string.punctuation) for Word in 
    text.split() if Word.strip(string.punctuation) != '']

# Call function
split_without_punc("Hey, you -- what are you doing?!")
# returns ['Hey', 'you', 'what', 'are', 'you', 'doing']


Funktion (traditionell)

Als traditionelle Funktion sind dies immer noch nur zwei Zeilen mit Listenverständnis (zusätzlich zu import string):

def split_without_punctuation2(text):

    # Split by whitespace
    words = text.split()

    # Strip punctuation from each Word
    return [Word.strip(ignore) for Word in words if Word.strip(ignore) != '']

split_without_punctuation2("Hey, you -- what are you doing?!")
# returns ['Hey', 'you', 'what', 'are', 'you', 'doing']

Natürlich bleiben auch Kontraktionen und Wörter mit Bindestrich erhalten. Sie können text.replace("-", " ") immer verwenden, um Bindestriche vor dem Split in Leerzeichen umzuwandeln.

Allgemeine Funktion ohne Lambda oder Listenverständnis

Für eine allgemeinere Lösung (bei der Sie die zu entfernenden Zeichen angeben können) und ohne Listenverständnis erhalten Sie Folgendes:

def split_without(text: str, ignore: str) -> list:

    # Split by whitespace
    split_string = text.split()

    # Strip any characters in the ignore string, and ignore empty strings
    words = []
    for Word in split_string:
        Word = Word.strip(ignore)
        if Word != '':
            words.append(Word)

    return words

# Situation-specific call to general function
import string
final_text = split_without("Hey, you - what are you doing?!", string.punctuation)
# returns ['Hey', 'you', 'what', 'are', 'you', 'doing']

Natürlich können Sie die Lambda-Funktion auch auf eine beliebige Zeichenfolge verallgemeinern.

1
cosmicFluke

Hier ist die Antwort mit einigen Erklärungen.

st = "Hey, you - what are you doing here!?"

# replace all the non alpha-numeric with space and then join.
new_string = ''.join([x.replace(x, ' ') if not x.isalnum() else x for x in st])
# output of new_string
'Hey  you  what are you doing here  '

# str.split() will remove all the empty string if separator is not provided
new_list = new_string.split()

# output of new_list
['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']

# we can join it to get a complete string without any non alpha-numeric character
' '.join(new_list)
# output
'Hey you what are you doing'

oder in einer Zeile können wir so machen:

(''.join([x.replace(x, ' ') if not x.isalnum() else x for x in st])).split()

# output
['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']

aktualisierte Antwort

1
Tasneem Haider

mit maketrans und translate können Sie dies einfach und ordentlich erledigen

import string
specials = ',.!?:;"()<>[]#$=-/'
trans = string.maketrans(specials, ' '*len(specials))
body = body.translate(trans)
words = body.strip().split()
1
Ritesh Sinha

Ich denke, das Folgende ist die beste Antwort auf Ihre Bedürfnisse:

\W+ ist möglicherweise für diesen Fall geeignet, für andere Fälle jedoch nicht geeignet.

filter(None, re.compile('[ |,|\-|!|?]').split( "Hey, you - what are you doing here!?")
0
nemozhp

Hier ist mein Los mit einem Split mit mehreren Deliminatoren:

def msplit( str, delims ):
  w = ''
  for z in str:
    if z not in delims:
        w += z
    else:
        if len(w) > 0 :
            yield w
        w = ''
  if len(w) > 0 :
    yield w
0
Martlark

habe dasselbe Problem wie @ooboo und finde dieses Thema @ ghostdog74 hat mich inspiriert, vielleicht findet jemand meine Lösung für nützlich

str1='adj:sg:nom:m1.m2.m3:pos'
splitat=':.'
''.join([ s if s not in splitat else ' ' for s in str1]).split()

geben Sie etwas in den Raum ein und teilen Sie das Zeichen mit dem gleichen Zeichen, wenn Sie keine Leerzeichen teilen möchten.

0
badas

Ich musste mir eine eigene Lösung einfallen lassen, da alles, was ich bisher getestet habe, irgendwann fehlgeschlagen ist.

>>> import re
>>> def split_words(text):
...     rgx = re.compile(r"((?:(?<!'|\w)(?:\w-?'?)+(?<!-))|(?:(?<='|\w)(?:\w-?'?)+(?=')))")
...     return rgx.findall(text)

Zumindest für die folgenden Beispiele scheint es in Ordnung zu sein.

>>> split_words("The hill-tops gleam in morning's spring.")
['The', 'hill-tops', 'gleam', 'in', "morning's", 'spring']
>>> split_words("I'd say it's James' 'time'.")
["I'd", 'say', "it's", "James'", 'time']
>>> split_words("tic-tac-toe's tic-tac-toe'll tic-tac'tic-tac we'll--if tic-tac")
["tic-tac-toe's", "tic-tac-toe'll", "tic-tac'tic-tac", "we'll", 'if', 'tic-tac']
>>> split_words("google.com [email protected] split_words")
['google', 'com', 'email', 'google', 'com', 'split_words']
>>> split_words("Kurt Friedrich Gödel (/ˈɡɜːrdəl/;[2] German: [ˈkʊɐ̯t ˈɡøːdl̩] (listen);")
['Kurt', 'Friedrich', 'Gödel', 'ˈɡɜːrdəl', '2', 'German', 'ˈkʊɐ', 't', 'ˈɡøːdl', 'listen']
>>> split_words("April 28, 1906 – January 14, 1978) was an Austro-Hungarian-born Austrian...")
['April', '28', '1906', 'January', '14', '1978', 'was', 'an', 'Austro-Hungarian-born', 'Austrian']
0
Wood
def get_words(s):
    l = []
    w = ''
    for c in s.lower():
        if c in '-!?,. ':
            if w != '': 
                l.append(w)
            w = ''
        else:
            w = w + c
    if w != '': 
        l.append(w)
    return l

Hier ist die Verwendung:

>>> s = "Hey, you - what are you doing here!?"
>>> print get_words(s)
['hey', 'you', 'what', 'are', 'you', 'doing', 'here']
0
inspectorrr

Ich mag den replace()-Weg am besten. Die folgende Prozedur ändert alle Trennzeichen, die in einer Zeichenfolge splitlist definiert sind, in das erste Trennzeichen in splitlist und teilt dann den Text auf diesem Trennzeichen auf. Es berücksichtigt auch, ob splitlist eine leere Zeichenfolge ist. Es gibt eine Liste von Wörtern ohne leere Zeichenfolgen zurück.

def split_string(text, splitlist):
    for sep in splitlist:
        text = text.replace(sep, splitlist[0])
    return filter(None, text.split(splitlist[0])) if splitlist else [text]

Hier ist meine Meinung dazu ....

def split_string(source,splitlist):
    splits = frozenset(splitlist)
    l = []
    s1 = ""
    for c in source:
        if c in splits:
            if s1:
                l.append(s1)
                s1 = ""
        else:
            print s1
            s1 = s1 + c
    if s1:
        l.append(s1)
    return l

>>>out = split_string("First Name,Last Name,Street Address,City,State,Zip Code",",")
>>>print out
>>>['First Name', 'Last Name', 'Street Address', 'City', 'State', 'Zip Code']

Ich musste dies kürzlich tun, wollte aber eine Funktion, die etwas mit der Standardbibliothek str.split übereinstimmt. Diese Funktion verhält sich wie die Standardbibliothek, wenn sie mit 0 oder 1 Argumenten aufgerufen wird.

def split_many(string, *separators):
    if len(separators) == 0:
        return string.split()
    if len(separators) > 1:
        table = {
            ord(separator): ord(separator[0])
            for separator in separators
        }
        string = string.translate(table)
    return string.split(separators[0])

NOTE: Diese Funktion ist nur nützlich, wenn Ihre Trennzeichen aus einem einzelnen Zeichen bestehen (wie in meinem Fall).

0
justinfay

Ich mag die Lösung von pprzemek, weil sie nicht davon ausgeht, dass die Begrenzer einzelne Zeichen sind, und nicht versucht, einen regulären Ausdruck zu verwenden (was nicht gut funktionieren würde, wenn die Anzahl der Trennzeichen verrückt wäre).

Hier ist eine besser lesbare Version der obigen Lösung, um die Übersichtlichkeit zu verbessern:

def split_string_on_multiple_separators(input_string, separators):
    buffer = [input_string]
    for sep in separators:
        strings = buffer
        buffer = []  # reset the buffer
        for s in strings:
            buffer = buffer + s.split(sep)

    return buffer
0
Everett

Wenn Sie eine reversible Operation wünschen (Begrenzung beibehalten), können Sie diese Funktion verwenden:

def tokenizeSentence_Reversible(sentence):
    setOfDelimiters = ['.', ' ', ',', '*', ';', '!']
    listOfTokens = [sentence]

    for delimiter in setOfDelimiters:
        newListOfTokens = []
        for ind, token in enumerate(listOfTokens):
            ll = [([delimiter, w] if ind > 0 else [w]) for ind, w in enumerate(token.split(delimiter))]
            listOfTokens = [item for sublist in ll for item in sublist] # flattens.
            listOfTokens = filter(None, listOfTokens) # Removes empty tokens: ''
            newListOfTokens.extend(listOfTokens)

        listOfTokens = newListOfTokens

    return listOfTokens
0
Nadav B