Der Grund ist, dass es sehr schwer ist, sich einen Fall vorzustellen, in dem es nützlich ist. Warum willst du das?
Glenn Maynard
10
@Glenn: Vor kurzem habe ich eine Frage zum Teilen einer langen Zeichenfolge in Stücke von n Wörtern gesehen. Eine der Lösungen war splitder String und gab dann einen Generator zurück, der am Ergebnis von arbeitete split. Das brachte mich zum Nachdenken, ob es eine Möglichkeit gab split, zunächst einen Generator zurückzugeben.
@GlennMaynard es kann nützlich sein für wirklich große nackte String / Datei-Analyse, aber jeder kann Generator-Parser selbst sehr einfach mit selbst gebrautem DFA und Ausbeute schreiben
Dmitry Ponyatov
Antworten:
77
Es ist sehr wahrscheinlich, dass re.finditerder Speicheraufwand relativ gering ist.
def split_iter(string):return(x.group(0)for x in re.finditer(r"[A-Za-z']+", string))
edit: Ich habe gerade bestätigt, dass dies in Python 3.2.1 konstanten Speicher benötigt, vorausgesetzt, meine Testmethode war korrekt. Ich habe eine Zeichenfolge von sehr großer Größe (ca. 1 GB) erstellt und dann mit einer forSchleife durch die Iterable iteriert (KEIN Listenverständnis, das zusätzlichen Speicher generiert hätte). Dies führte nicht zu einem merklichen Speicherwachstum (das heißt, wenn das Speicherwachstum zunahm, war es weit weniger als die 1-GB-Zeichenfolge).
Ausgezeichnet! Ich hatte den Finditer vergessen. Wenn man daran interessiert wäre, so etwas wie Splitlines zu machen, würde ich vorschlagen, diese RE zu verwenden: '(. * \ N |. + $)' Str.splitlines hackt die trainling newline ab (etwas, das ich nicht wirklich mag ... ); Wenn Sie diesen Teil des Verhaltens replizieren möchten, können Sie die Gruppierung verwenden: (m.group (2) oder m.group (3) für m in re.finditer ('((. *) \ n | (. +)) $) ', s)). PS: Ich denke, die äußeren Paren im RE werden nicht benötigt. Ich fühle mich einfach unwohl bei der Verwendung von | ohne paren: P
allyourcode
3
Was ist mit Leistung? Der Abgleich sollte langsamer sein als die normale Suche.
Anatoly Techtonik
1
Wie würden Sie diese split_iter-Funktion so umschreiben, dass sie funktioniert a_string.split("delimiter")?
Moberg
split akzeptiert ohnehin reguläre Ausdrücke, daher ist es nicht wirklich schneller. Wenn Sie den zurückgegebenen Wert auf die nächste Weise verwenden möchten, sehen Sie sich meine Antwort unten an ...
Veltzer Doron
str.split()akzeptiert keine regulären Ausdrücke, daran re.split()denken Sie ...
alexis
17
Die effizienteste Art, wie ich mir vorstellen kann, eine mit dem offsetParameter der str.find()Methode zu schreiben . Dies vermeidet viel Speicherbedarf und ist auf den Overhead eines regulären Ausdrucks angewiesen, wenn dieser nicht benötigt wird.
[2016-8-2 bearbeiten: aktualisiert, um optional Regex-Trennzeichen zu unterstützen]
def isplit(source, sep=None, regex=False):"""
generator version of str.split()
:param source:
source string (unicode or bytes)
:param sep:
separator to split on.
:param regex:
if True, will treat sep as regular expression.
:returns:
generator yielding elements of string.
"""if sep isNone:# mimic default python behavior
source = source.strip()
sep ="\\s+"if isinstance(source, bytes):
sep = sep.encode("ascii")
regex =Trueif regex:# version using re.finditer()ifnot hasattr(sep,"finditer"):
sep = re.compile(sep)
start =0for m in sep.finditer(source):
idx = m.start()assert idx >= startyield source[start:idx]
start = m.end()yield source[start:]else:# version using str.find(), less overhead than re.finditer()
sepsize = len(sep)
start =0whileTrue:
idx = source.find(sep, start)if idx ==-1:yield source[start:]returnyield source[start:idx]
start = idx + sepsize
Dies kann verwendet werden, wie Sie wollen ...
>>>print list(isplit("abcb","b"))['a','c','']
Während jedes Mal, wenn find () oder Slicing ausgeführt wird, ein wenig nach Kosten in der Zeichenfolge gesucht wird, sollte dies minimal sein, da Zeichenfolgen als zusammenhängende Arrays im Speicher dargestellt werden.
@ErikKaplun Da die Regex-Logik für die Elemente komplexer sein kann als für ihre Trennzeichen. In meinem Fall wollte ich jede Zeile einzeln verarbeiten, damit ich zurückmelden kann, wenn eine Zeile nicht übereinstimmt.
Rovyko
8
Habe einige Leistungstests für die verschiedenen vorgeschlagenen Methoden durchgeführt (ich werde sie hier nicht wiederholen). Einige Ergebnisse:
str.split (Standard = 0,3461570239996945
manuelle Suche (nach Zeichen) (eine der Antworten von Dave Webb) = 0.8260340550004912
re.finditer (Antwort von Ninjagecko) = 0,698872097000276
str.find (eine der Antworten von Eli Collins) = 0,7230395330007013
itertools.takewhile (Antwort von Ignacio Vazquez-Abrams) = 2.023023967998597
str.split(..., maxsplit=1) Rekursion = N / A †
† Die Rekursionsantworten ( string.splitmit maxsplit = 1) werden nicht in angemessener Zeit abgeschlossen, da string.splitsie bei kürzeren Zeichenfolgen möglicherweise besser funktionieren, aber dann kann ich den Anwendungsfall für kurze Zeichenfolgen nicht sehen, bei denen der Speicher ohnehin kein Problem darstellt.
Getestet mit timeit:
the_text ="100 "*9999+"100"def test_function( method ):def fn():
total =0for x in method( the_text ):
total += int( x )return totalreturn fn
Dies wirft eine weitere Frage auf, warum string.splites trotz seiner Speichernutzung so viel schneller geht.
Dies liegt daran, dass der Speicher langsamer als die CPU ist und in diesem Fall die Liste von Blöcken geladen wird, wobei alle anderen Elemente Element für Element geladen werden. Aus dem gleichen Grund werden viele Wissenschaftler Ihnen sagen, dass verknüpfte Listen schneller und weniger komplex sind, während Ihr Computer mit Arrays häufig schneller ist, was sich leichter optimieren lässt. Sie können nicht davon ausgehen, dass eine Option schneller als eine andere ist. Testen Sie sie! +1 zum Testen.
Benoît P
Das Problem tritt in den nächsten Schritten einer Verarbeitungskette auf. Wenn Sie dann einen bestimmten Block suchen und den Rest ignorieren möchten, wenn Sie ihn finden, haben Sie die Berechtigung, anstelle der integrierten Lösung einen generatorbasierten Split zu verwenden.
jgomo3
6
Hier ist meine Implementierung, die viel, viel schneller und vollständiger ist als die anderen Antworten hier. Es hat 4 separate Unterfunktionen für verschiedene Fälle.
Ich kopiere einfach die Dokumentzeichenfolge der str_splitHauptfunktion:
str_split(s,*delims, empty=None)
sTeilen Sie die Zeichenfolge durch die restlichen Argumente und lassen Sie möglicherweise leere Teile weg (das emptySchlüsselwortargument ist dafür verantwortlich). Dies ist eine Generatorfunktion.
Wenn nur ein Trennzeichen angegeben wird, wird die Zeichenfolge einfach durch dieses getrennt.
emptyist dann Truestandardmäßig.
Wenn mehrere Trennzeichen angegeben werden, wird die Zeichenfolge standardmäßig durch die längstmöglichen Folgen dieser Trennzeichen geteilt, oder, falls emptyfestgelegt
True, werden auch leere Zeichenfolgen zwischen den Trennzeichen eingeschlossen. Beachten Sie, dass die Trennzeichen in diesem Fall nur einzelne Zeichen sein dürfen.
Wenn keine Trennzeichen angegeben sind, string.whitespacewird verwendet, sodass der Effekt der gleiche ist wie str.split(), außer dass diese Funktion ein Generator ist.
str_split('aaa\\t bb c \\n')->'aaa','bb','c'
import stringdef _str_split_chars(s, delims):"Split the string `s` by characters contained in `delims`, including the \
empty parts between two consecutive delimiters"
start =0for i, c in enumerate(s):if c in delims:yield s[start:i]
start = i+1yield s[start:]def _str_split_chars_ne(s, delims):"Split the string `s` by longest possible sequences of characters \
contained in `delims`"
start =0
in_s =Falsefor i, c in enumerate(s):if c in delims:if in_s:yield s[start:i]
in_s =Falseelse:ifnot in_s:
in_s =True
start = iif in_s:yield s[start:]def _str_split_word(s, delim):"Split the string `s` by the string `delim`"
dlen = len(delim)
start =0try:whileTrue:
i = s.index(delim, start)yield s[start:i]
start = i+dlenexceptValueError:passyield s[start:]def _str_split_word_ne(s, delim):"Split the string `s` by the string `delim`, not including empty parts \
between two consecutive delimiters"
dlen = len(delim)
start =0try:whileTrue:
i = s.index(delim, start)if start!=i:yield s[start:i]
start = i+dlenexceptValueError:passif start<len(s):yield s[start:]def str_split(s,*delims, empty=None):"""\
Split the string `s` by the rest of the arguments, possibly omitting
empty parts (`empty` keyword argument is responsible for that).
This is a generator function.
When only one delimiter is supplied, the string is simply split by it.
`empty` is then `True` by default.
str_split('[]aaa[][]bb[c', '[]')
-> '', 'aaa', '', 'bb[c'
str_split('[]aaa[][]bb[c', '[]', empty=False)
-> 'aaa', 'bb[c'
When multiple delimiters are supplied, the string is split by longest
possible sequences of those delimiters by default, or, if `empty` is set to
`True`, empty strings between the delimiters are also included. Note that
the delimiters in this case may only be single characters.
str_split('aaa, bb : c;', ' ', ',', ':', ';')
-> 'aaa', 'bb', 'c'
str_split('aaa, bb : c;', *' ,:;', empty=True)
-> 'aaa', '', 'bb', '', '', 'c', ''
When no delimiters are supplied, `string.whitespace` is used, so the effect
is the same as `str.split()`, except this function is a generator.
str_split('aaa\\t bb c \\n')
-> 'aaa', 'bb', 'c'
"""if len(delims)==1:
f = _str_split_word if empty isNoneor empty else _str_split_word_nereturn f(s, delims[0])if len(delims)==0:
delims = string.whitespace
delims = set(delims)if len(delims)>=4else''.join(delims)if any(len(d)>1for d in delims):raiseValueError("Only 1-character multiple delimiters are supported")
f = _str_split_chars if empty else _str_split_chars_nereturn f(s, delims)
Diese Funktion funktioniert in Python 3, und eine einfache, wenn auch ziemlich hässliche Korrektur kann angewendet werden, damit sie sowohl in 2 als auch in 3 Versionen funktioniert. Die ersten Zeilen der Funktion sollten geändert werden in:
Nein, aber es sollte einfach genug sein, eine mit zu schreiben itertools.takewhile().
BEARBEITEN:
Sehr einfache, halb kaputte Implementierung:
import itertools
import string
def isplitwords(s):
i = iter(s)whileTrue:
r =[]for c in itertools.takewhile(lambda x:not x in string.whitespace, i):
r.append(c)else:if r:yield''.join(r)continueelse:raiseStopIteration()
@Ignacio: Das Beispiel in docs verwendet eine Liste von Ganzzahlen, um die Verwendung von zu veranschaulichen takeWhile. Was wäre gut, predicateum eine Zeichenfolge mit (standardmäßig split) in Wörter aufzuteilen takeWhile()?
Manoj Govindan
Suchen Sie nach Präsenz in string.whitespace.
Ignacio Vazquez-Abrams
Das Trennzeichen kann mehrere Zeichen haben,'abc<def<>ghi<><>lmn'.split('<>') == ['abc<def', 'ghi', '', 'lmn']
kennytm
@Ignacio: Können Sie Ihrer Antwort ein Beispiel hinzufügen?
Manoj Govindan
1
Einfach zu schreiben, aber viele Größenordnungen langsamer. Dies ist eine Operation, die wirklich in nativem Code implementiert werden sollte.
Glenn Maynard
3
Ich sehe keinen offensichtlichen Vorteil für eine Generatorversion von split(). Das Generatorobjekt muss die gesamte Zeichenfolge enthalten, über die iteriert werden soll, damit Sie keinen Speicher mit einem Generator sparen.
Wenn Sie eine schreiben wollten, wäre es allerdings ziemlich einfach:
import string
def gsplit(s,sep=string.whitespace):
word =[]for c in s:if c in sep:if word:yield"".join(word)
word =[]else:
word.append(c)if word:yield"".join(word)
Sie würden den verwendeten Speicher halbieren, indem Sie nicht in jedem resultierenden Teil eine zweite Kopie der Zeichenfolge sowie den Array- und Objekt-Overhead speichern müssen (der normalerweise höher ist als die Zeichenfolgen selbst). Dies spielt jedoch im Allgemeinen keine Rolle (wenn Sie Zeichenfolgen so groß aufteilen, dass dies wichtig ist, machen Sie wahrscheinlich etwas falsch), und selbst eine native C-Generator-Implementierung wäre immer erheblich langsamer als alles auf einmal.
Glenn Maynard
@Glenn Maynard - das habe ich gerade gemerkt. Aus irgendeinem Grund würde der Generator ursprünglich eine Kopie der Zeichenfolge anstelle einer Referenz speichern. Ein kurzer Check mit id()hat mich richtig gestellt. Und da Zeichenfolgen unveränderlich sind, müssen Sie sich natürlich keine Sorgen machen, dass jemand die ursprüngliche Zeichenfolge ändert, während Sie darüber iterieren.
Dave Webb
6
Ist der Hauptpunkt bei der Verwendung eines Generators nicht die Speichernutzung, sondern die Möglichkeit, dass Sie sich die gesamte Zeichenfolge teilen müssen, wenn Sie vorzeitig beenden möchten? (Das ist kein Kommentar zu Ihrer speziellen Lösung, ich war nur überrascht von der Diskussion über das Gedächtnis).
Scott Griffiths
@Scott: Es ist schwer, sich einen Fall vorzustellen, in dem das wirklich ein Gewinn ist - 1: Sie möchten aufhören, sich auf halbem Weg zu teilen, 2: Sie wissen nicht, wie viele Wörter Sie im Voraus teilen, 3: Sie haben eine groß genug, damit es wichtig ist, und 4: Sie hören konsequent früh genug auf, damit es ein bedeutender Gewinn für str.split ist. Das sind sehr enge Bedingungen.
Glenn Maynard
4
Sie können einen viel höheren Nutzen haben, wenn Ihre Zeichenfolge ebenfalls träge generiert wird (z. B. durch Netzwerkverkehr oder Lesen von Dateien)
Lie Ryan
3
Ich habe eine Version von @ ninjageckos Antwort geschrieben, die sich eher wie string.split verhält (dh Leerzeichen, die standardmäßig begrenzt sind und Sie können ein Trennzeichen angeben).
def isplit(string, delimiter =None):"""Like string.split but returns an iterator (lazy)
Multiple character delimters are not handled.
"""if delimiter isNone:# Whitespace delimited by default
delim = r"\s"elif len(delimiter)!=1:raiseValueError("Can only handle single character delimiters",
delimiter)else:# Escape, incase it's "\", "*" etc.
delim = re.escape(delimiter)return(x.group(0)for x in re.finditer(r"[^{}]+".format(delim), string))
Hier sind die Tests, die ich verwendet habe (sowohl in Python 3 als auch in Python 2):
# Wrapper to make it a listdef helper(*args,**kwargs):return list(isplit(*args,**kwargs))# Normal delimitersassert helper("1,2,3",",")==["1","2","3"]assert helper("1;2;3,",";")==["1","2","3,"]assert helper("1;2 ;3, ",";")==["1","2 ","3, "]# Whitespaceassert helper("1 2 3")==["1","2","3"]assert helper("1\t2\t3")==["1","2","3"]assert helper("1\t2 \t3")==["1","2","3"]assert helper("1\n2\n3")==["1","2","3"]# Surrounding whitespace droppedassert helper(" 1 2 3 ")==["1","2","3"]# Regex special charactersassert helper(r"1\2\3","\\")==["1","2","3"]assert helper(r"1*2*3","*")==["1","2","3"]# No multi-char delimiters allowedtry:
helper(r"1,.2,.3",",.")assertFalseexceptValueError:pass
Das Regex-Modul von Python sagt, dass es "das Richtige" für Unicode-Leerzeichen tut , aber ich habe es nicht wirklich getestet.
Wenn Sie möchten auch in der Lage sein lesen einen Iterator (sowie Rückkehr eins) versuchen Sie dies:
import itertools as it
def iter_split(string, sep=None):
sep = sep or' '
groups = it.groupby(string,lambda s: s != sep)return(''.join(g)for k, g in groups if k)
Beachten Sie, dass more_itertools.split_at () bei jedem Aufruf immer noch eine neu zugewiesene Liste verwendet. Dies gibt zwar einen Iterator zurück, erreicht jedoch nicht den konstanten Speicherbedarf. Je nachdem, warum Sie einen Iterator haben wollten, kann dies hilfreich sein oder auch nicht.
Jcater
@jcater Guter Punkt. Die Zwischenwerte werden tatsächlich entsprechend ihrer Implementierung als Unterlisten innerhalb des Iterators gepuffert . Man könnte die Quelle anpassen, um Listen durch Iteratoren zu ersetzen, itertools.chainErgebnisse mit einem Listenverständnis anzufügen und auszuwerten. Je nach Bedarf und Anfrage kann ich ein Beispiel posten.
Pylang
2
Ich wollte zeigen, wie man mit der find_iter-Lösung einen Generator für bestimmte Trennzeichen zurückgibt und dann mit dem paarweisen Rezept von itertools eine vorherige nächste Iteration erstellt, die die tatsächlichen Wörter wie in der ursprünglichen Split-Methode erhält.
from more_itertools import pairwise
import re
string ="dasdha hasud hasuid hsuia dhsuai dhasiu dhaui d"
delimiter =" "# split according to the given delimiter including segments beginning at the beginning and ending at the endfor prev, curr in pairwise(re.finditer("^|[{0}]+|$".format(delimiter), string)):print(string[prev.end(): curr.start()])
Hinweis:
Ich verwende prev & curr anstelle von prev & next, da das Überschreiben von next in Python eine sehr schlechte Idee ist
def split_generator(f,s):"""
f is a string, s is the substring we split on.
This produces a generator rather than a possibly
memory intensive list.
"""
i=0
j=0while j<len(f):if i>=len(f):yield f[j:]
j=i
elif f[i]!= s:
i=i+1else:yield[f[j:i]]
j=i+1
i=i+1
split
der String und gab dann einen Generator zurück, der am Ergebnis von arbeitetesplit
. Das brachte mich zum Nachdenken, ob es eine Möglichkeit gabsplit
, zunächst einen Generator zurückzugeben.Antworten:
Es ist sehr wahrscheinlich, dass
re.finditer
der Speicheraufwand relativ gering ist.Demo:
edit: Ich habe gerade bestätigt, dass dies in Python 3.2.1 konstanten Speicher benötigt, vorausgesetzt, meine Testmethode war korrekt. Ich habe eine Zeichenfolge von sehr großer Größe (ca. 1 GB) erstellt und dann mit einer
for
Schleife durch die Iterable iteriert (KEIN Listenverständnis, das zusätzlichen Speicher generiert hätte). Dies führte nicht zu einem merklichen Speicherwachstum (das heißt, wenn das Speicherwachstum zunahm, war es weit weniger als die 1-GB-Zeichenfolge).quelle
a_string.split("delimiter")
?str.split()
akzeptiert keine regulären Ausdrücke, daranre.split()
denken Sie ...Die effizienteste Art, wie ich mir vorstellen kann, eine mit dem
offset
Parameter derstr.find()
Methode zu schreiben . Dies vermeidet viel Speicherbedarf und ist auf den Overhead eines regulären Ausdrucks angewiesen, wenn dieser nicht benötigt wird.[2016-8-2 bearbeiten: aktualisiert, um optional Regex-Trennzeichen zu unterstützen]
Dies kann verwendet werden, wie Sie wollen ...
Während jedes Mal, wenn find () oder Slicing ausgeführt wird, ein wenig nach Kosten in der Zeichenfolge gesucht wird, sollte dies minimal sein, da Zeichenfolgen als zusammenhängende Arrays im Speicher dargestellt werden.
quelle
Dies ist eine Generatorversion von
split()
implementiert überre.search()
, die nicht das Problem hat, zu viele Teilzeichenfolgen zuzuweisen.BEARBEITEN: Der Umgang mit umgebenden Leerzeichen wurde korrigiert, wenn keine Trennzeichen angegeben wurden.
quelle
re.finditer
?Habe einige Leistungstests für die verschiedenen vorgeschlagenen Methoden durchgeführt (ich werde sie hier nicht wiederholen). Einige Ergebnisse:
str.split
(Standard = 0,3461570239996945re.finditer
(Antwort von Ninjagecko) = 0,698872097000276str.find
(eine der Antworten von Eli Collins) = 0,7230395330007013itertools.takewhile
(Antwort von Ignacio Vazquez-Abrams) = 2.023023967998597str.split(..., maxsplit=1)
Rekursion = N / A †† Die Rekursionsantworten (
string.split
mitmaxsplit = 1
) werden nicht in angemessener Zeit abgeschlossen, dastring.split
sie bei kürzeren Zeichenfolgen möglicherweise besser funktionieren, aber dann kann ich den Anwendungsfall für kurze Zeichenfolgen nicht sehen, bei denen der Speicher ohnehin kein Problem darstellt.Getestet mit
timeit
:Dies wirft eine weitere Frage auf, warum
string.split
es trotz seiner Speichernutzung so viel schneller geht.quelle
Hier ist meine Implementierung, die viel, viel schneller und vollständiger ist als die anderen Antworten hier. Es hat 4 separate Unterfunktionen für verschiedene Fälle.
Ich kopiere einfach die Dokumentzeichenfolge der
str_split
Hauptfunktion:s
Teilen Sie die Zeichenfolge durch die restlichen Argumente und lassen Sie möglicherweise leere Teile weg (dasempty
Schlüsselwortargument ist dafür verantwortlich). Dies ist eine Generatorfunktion.Wenn nur ein Trennzeichen angegeben wird, wird die Zeichenfolge einfach durch dieses getrennt.
empty
ist dannTrue
standardmäßig.Wenn mehrere Trennzeichen angegeben werden, wird die Zeichenfolge standardmäßig durch die längstmöglichen Folgen dieser Trennzeichen geteilt, oder, falls
empty
festgelegtTrue
, werden auch leere Zeichenfolgen zwischen den Trennzeichen eingeschlossen. Beachten Sie, dass die Trennzeichen in diesem Fall nur einzelne Zeichen sein dürfen.Wenn keine Trennzeichen angegeben sind,
string.whitespace
wird verwendet, sodass der Effekt der gleiche ist wiestr.split()
, außer dass diese Funktion ein Generator ist.Diese Funktion funktioniert in Python 3, und eine einfache, wenn auch ziemlich hässliche Korrektur kann angewendet werden, damit sie sowohl in 2 als auch in 3 Versionen funktioniert. Die ersten Zeilen der Funktion sollten geändert werden in:
quelle
Nein, aber es sollte einfach genug sein, eine mit zu schreiben
itertools.takewhile()
.BEARBEITEN:
Sehr einfache, halb kaputte Implementierung:
quelle
takeWhile
. Was wäre gut,predicate
um eine Zeichenfolge mit (standardmäßigsplit
) in Wörter aufzuteilentakeWhile()
?string.whitespace
.'abc<def<>ghi<><>lmn'.split('<>') == ['abc<def', 'ghi', '', 'lmn']
Ich sehe keinen offensichtlichen Vorteil für eine Generatorversion vonsplit()
. Das Generatorobjekt muss die gesamte Zeichenfolge enthalten, über die iteriert werden soll, damit Sie keinen Speicher mit einem Generator sparen.Wenn Sie eine schreiben wollten, wäre es allerdings ziemlich einfach:
quelle
id()
hat mich richtig gestellt. Und da Zeichenfolgen unveränderlich sind, müssen Sie sich natürlich keine Sorgen machen, dass jemand die ursprüngliche Zeichenfolge ändert, während Sie darüber iterieren.Ich habe eine Version von @ ninjageckos Antwort geschrieben, die sich eher wie string.split verhält (dh Leerzeichen, die standardmäßig begrenzt sind und Sie können ein Trennzeichen angeben).
Hier sind die Tests, die ich verwendet habe (sowohl in Python 3 als auch in Python 2):
Das Regex-Modul von Python sagt, dass es "das Richtige" für Unicode-Leerzeichen tut , aber ich habe es nicht wirklich getestet.
Auch als Kernstück erhältlich .
quelle
Wenn Sie möchten auch in der Lage sein lesen einen Iterator (sowie Rückkehr eins) versuchen Sie dies:
Verwendung
quelle
more_itertools.split_at
bietet ein Analogonstr.split
für Iteratoren.more_itertools
ist ein Paket von Drittanbietern.quelle
itertools.chain
Ergebnisse mit einem Listenverständnis anzufügen und auszuwerten. Je nach Bedarf und Anfrage kann ich ein Beispiel posten.Ich wollte zeigen, wie man mit der find_iter-Lösung einen Generator für bestimmte Trennzeichen zurückgibt und dann mit dem paarweisen Rezept von itertools eine vorherige nächste Iteration erstellt, die die tatsächlichen Wörter wie in der ursprünglichen Split-Methode erhält.
Hinweis:
quelle
Dümmste Methode ohne Regex / Itertools:
quelle
quelle
[f[j:i]]
und nichtf[j:i]
?Hier ist eine einfache Antwort
quelle