Angenommen, diese Zeichenfolge:
The fox jumped over the log.
Sich in etwas verwandeln:
The fox jumped over the log.
Was ist am einfachsten (1-2 Zeilen), um dies zu erreichen, ohne zu teilen und in Listen zu gehen?
Angenommen, diese Zeichenfolge:
The fox jumped over the log.
Sich in etwas verwandeln:
The fox jumped over the log.
Was ist am einfachsten (1-2 Zeilen), um dies zu erreichen, ohne zu teilen und in Listen zu gehen?
Antworten:
>>> import re
>>> re.sub(' +', ' ', 'The quick brown fox')
'The quick brown fox'
string.split
behandelt auch alle Arten von Leerzeichen.
re.sub(' {2,}', ' ', 'The quick brown fox')
, um redundantes Ersetzen von Single-Space durch Single-Space zu verhindern .
foo
ist dein String:
" ".join(foo.split())
Seien Sie gewarnt, obwohl dadurch "alle Leerzeichen (Leerzeichen, Tabulator, Zeilenumbruch, Rückgabe, Formularvorschub)" entfernt werden (dank hhsaffar , siehe Kommentare). Dh "this is \t a test\n"
wird effektiv als enden "this is a test"
.
import re
s = "The fox jumped over the log."
re.sub("\s\s+" , " ", s)
oder
re.sub("\s\s+", " ", s)
da das Leerzeichen vor dem Komma in PEP 8 als Pet Peeve aufgeführt ist , wie von Benutzer Martin Thoma in den Kommentaren erwähnt.
r"\s\s+"
damit er nicht versucht, bereits einzelne Leerzeichen zu ersetzen.
"\s{2,}"
anstelle einer Problemumgehung, wenn Sie das mäßig fortgeschrittene Regex-Verhalten nicht kennen?
s
, sondern den neuen Wert zurückgibt.
\s+
würde dazu führen, dass in der Zeile " ein oder mehrere Leerzeichen durch ein Leerzeichen ersetzen" und nicht " zwei oder mehr Leerzeichen durch ein Leerzeichen ersetzen " steht. Ersteres lässt mich sofort innehalten und denken: "Warum ein Leerzeichen durch ein Leerzeichen ersetzen? Das ist albern." Für mich ist das ein (sehr geringer) Code-Geruch. Ich würde eigentlich nicht erwarten , dass es überhaupt einen Unterschied in der Leistung sein zwischen den beiden, wie es geht in eine neue Zeichenfolge zu kopieren sowieso, und muss aufhören und Test unabhängig davon , wo der Raum kopiert wird aus .
\s\s+
da dies ein TAB-Zeichen nicht auf ein normales Leerzeichen normalisiert. Ein SPACE + TAB wird auf diese Weise ersetzt.
Wenn Sie reguläre Ausdrücke mit "\ s" verwenden und einfache string.split () ausführen, werden auch andere Leerzeichen entfernt - wie Zeilenumbrüche, Zeilenumbrüche und Tabulatoren. Es sei denn , dies gewünscht ist, um nur zu tun mehrere Räume , präsentiere ich diese Beispiele.
Ich habe 11 Absätze, 1000 Wörter, 6665 Bytes Lorem Ipsum verwendet , um realistische Zeittests zu erhalten, und zusätzliche Leerzeichen mit zufälliger Länge verwendet:
original_string = ''.join(word + (' ' * random.randint(1, 10)) for word in lorem_ipsum.split(' '))
Der Einzeiler macht im Wesentlichen einen Streifen von allen führenden / nachfolgenden Leerzeichen und bewahrt einen führenden / nachfolgenden Leerzeichen (aber nur EINEN ;-).
# setup = '''
import re
def while_replace(string):
while ' ' in string:
string = string.replace(' ', ' ')
return string
def re_replace(string):
return re.sub(r' {2,}' , ' ', string)
def proper_join(string):
split_string = string.split(' ')
# To account for leading/trailing spaces that would simply be removed
beg = ' ' if not split_string[ 0] else ''
end = ' ' if not split_string[-1] else ''
# versus simply ' '.join(item for item in string.split(' ') if item)
return beg + ' '.join(item for item in split_string if item) + end
original_string = """Lorem ipsum ... no, really, it kept going... malesuada enim feugiat. Integer imperdiet erat."""
assert while_replace(original_string) == re_replace(original_string) == proper_join(original_string)
#'''
# while_replace_test
new_string = original_string[:]
new_string = while_replace(new_string)
assert new_string != original_string
# re_replace_test
new_string = original_string[:]
new_string = re_replace(new_string)
assert new_string != original_string
# proper_join_test
new_string = original_string[:]
new_string = proper_join(new_string)
assert new_string != original_string
HINWEIS: Die " Beachten Sie, dass das Haupt while
Version" hat eine Kopie der original_string
, wie ich glaube, einmal beim ersten Lauf modifizierten, aufeinanderfolgenden Läufe schneller gemacht (wenn auch nur ein bisschen). Da dies Zeit hinzufügt, habe ich diese Zeichenfolgenkopie zu den beiden anderen hinzugefügt, sodass die Zeiten nur den Unterschied in der Logik zeigten. stmt
auf timeit
Instanzen wird nur einmal durchgeführt werden ; Auf die ursprüngliche Art und Weise, wie ich das gemacht habe, arbeitete die while
Schleife auf demselben Label original_string
, daher gab es beim zweiten Durchlauf nichts zu tun. Die Art und Weise, wie es jetzt eingerichtet ist, eine Funktion mit zwei verschiedenen Bezeichnungen aufzurufen, ist kein Problem. Ich habe assert
allen Mitarbeitern Aussagen hinzugefügt , um zu überprüfen, ob wir bei jeder Iteration etwas ändern (für diejenigen, die möglicherweise zweifelhaft sind). ZB ändern Sie dies und es bricht:
# while_replace_test
new_string = original_string[:]
new_string = while_replace(new_string)
assert new_string != original_string # will break the 2nd iteration
while ' ' in original_string:
original_string = original_string.replace(' ', ' ')
Tests run on a laptop with an i5 processor running Windows 7 (64-bit).
timeit.Timer(stmt = test, setup = setup).repeat(7, 1000)
test_string = 'The fox jumped over\n\t the log.' # trivial
Python 2.7.3, 32-bit, Windows
test | minum | maximum | average | median
---------------------+------------+------------+------------+-----------
while_replace_test | 0.001066 | 0.001260 | 0.001128 | 0.001092
re_replace_test | 0.003074 | 0.003941 | 0.003357 | 0.003349
proper_join_test | 0.002783 | 0.004829 | 0.003554 | 0.003035
Python 2.7.3, 64-bit, Windows
test | minum | maximum | average | median
---------------------+------------+------------+------------+-----------
while_replace_test | 0.001025 | 0.001079 | 0.001052 | 0.001051
re_replace_test | 0.003213 | 0.004512 | 0.003656 | 0.003504
proper_join_test | 0.002760 | 0.006361 | 0.004626 | 0.004600
Python 3.2.3, 32-bit, Windows
test | minum | maximum | average | median
---------------------+------------+------------+------------+-----------
while_replace_test | 0.001350 | 0.002302 | 0.001639 | 0.001357
re_replace_test | 0.006797 | 0.008107 | 0.007319 | 0.007440
proper_join_test | 0.002863 | 0.003356 | 0.003026 | 0.002975
Python 3.3.3, 64-bit, Windows
test | minum | maximum | average | median
---------------------+------------+------------+------------+-----------
while_replace_test | 0.001444 | 0.001490 | 0.001460 | 0.001459
re_replace_test | 0.011771 | 0.012598 | 0.012082 | 0.011910
proper_join_test | 0.003741 | 0.005933 | 0.004341 | 0.004009
test_string = lorem_ipsum
# Thanks to http://www.lipsum.com/
# "Generated 11 paragraphs, 1000 words, 6665 bytes of Lorem Ipsum"
Python 2.7.3, 32-bit
test | minum | maximum | average | median
---------------------+------------+------------+------------+-----------
while_replace_test | 0.342602 | 0.387803 | 0.359319 | 0.356284
re_replace_test | 0.337571 | 0.359821 | 0.348876 | 0.348006
proper_join_test | 0.381654 | 0.395349 | 0.388304 | 0.388193
Python 2.7.3, 64-bit
test | minum | maximum | average | median
---------------------+------------+------------+------------+-----------
while_replace_test | 0.227471 | 0.268340 | 0.240884 | 0.236776
re_replace_test | 0.301516 | 0.325730 | 0.308626 | 0.307852
proper_join_test | 0.358766 | 0.383736 | 0.370958 | 0.371866
Python 3.2.3, 32-bit
test | minum | maximum | average | median
---------------------+------------+------------+------------+-----------
while_replace_test | 0.438480 | 0.463380 | 0.447953 | 0.446646
re_replace_test | 0.463729 | 0.490947 | 0.472496 | 0.468778
proper_join_test | 0.397022 | 0.427817 | 0.406612 | 0.402053
Python 3.3.3, 64-bit
test | minum | maximum | average | median
---------------------+------------+------------+------------+-----------
while_replace_test | 0.284495 | 0.294025 | 0.288735 | 0.289153
re_replace_test | 0.501351 | 0.525673 | 0.511347 | 0.508467
proper_join_test | 0.422011 | 0.448736 | 0.436196 | 0.440318
Für die triviale Zeichenfolge scheint eine while-Schleife die schnellste zu sein, gefolgt von der Aufteilung / Verknüpfung der Pythonic-Zeichenfolge und der Regex, die die Rückseite nach oben zieht.
Für nicht triviale Zeichenfolgen scheint es ein bisschen mehr zu geben. 32-Bit 2,7? Es ist Regex zur Rettung! 2,7 64-Bit? Eine while
Schleife ist mit einem anständigen Abstand am besten. 32-Bit 3.2, gehen Sie mit dem "richtigen" join
. 64-Bit 3.3, machen Sie eine while
Schleife. Nochmal.
Am Ende kann man die Leistung verbessern, wenn / wo / wenn nötig , aber es ist immer am besten, sich an das Mantra zu erinnern :
IANAL, YMMV, Vorbehalt Emptor!
' '.join(the_string.split())
da dies der übliche Anwendungsfall ist, aber ich möchte mich für Ihre Arbeit bedanken!
' '.join(p for p in s.split(' ') if p)
<- verlor immer noch Lead / Trailing Spaces, machte aber mehrere Spaces aus. Um sie zu behalten, muss man gerne tun parts = s.split(' '); (' ' if not parts[0] else '') + ' '.join(p for p in s.split(' ') if p) + (' ' if not parts[-1] else '')
!
Ich muss dem Kommentar von Paul McGuire zustimmen. Mir,
' '.join(the_string.split())
ist dem Auspeitschen einer Regex weitaus vorzuziehen.
Meine Messungen (Linux und Python 2.5) zeigen, dass der Split-Then-Join fast fünfmal schneller ist als "re.sub (...)" und immer noch dreimal schneller, wenn Sie den regulären Ausdruck einmal vorkompilieren und den Vorgang ausführen mehrmals. Und es ist in jeder Hinsicht leichter zu verstehen - viel mehr pythonisch.
Sie können die Zeichenfolgenteilungstechnik auch in einem Pandas DataFrame verwenden, ohne .apply (..) verwenden zu müssen. Dies ist nützlich, wenn Sie den Vorgang für eine große Anzahl von Zeichenfolgen schnell ausführen müssen. Hier steht es in einer Zeile:
df['message'] = (df['message'].str.split()).str.join(' ')
import re
string = re.sub('[ \t\n]+', ' ', 'The quick brown \n\n \t fox')
Dadurch werden alle Registerkarten, neuen Linien und mehrere Leerzeichen mit einem Leerzeichen entfernt.
Ich habe die folgende Methode ausprobiert und sie funktioniert sogar im Extremfall wie:
str1=' I live on earth '
' '.join(str1.split())
Wenn Sie jedoch einen regulären Ausdruck bevorzugen, können Sie Folgendes tun:
re.sub('\s+', ' ', str1)
Es muss zwar eine Vorverarbeitung durchgeführt werden, um den nachgestellten und endenden Speicherplatz zu entfernen.
In einigen Fällen ist es wünschenswert, aufeinanderfolgende Vorkommen jedes Leerzeichen durch eine einzelne Instanz dieses Zeichens zu ersetzen . Sie würden dazu einen regulären Ausdruck mit Rückreferenzen verwenden.
(\s)\1{1,}
Entspricht einem beliebigen Leerzeichen, gefolgt von einem oder mehreren Vorkommen dieses Zeichens. Jetzt müssen Sie nur noch die erste Gruppe ( \1
) als Ersatz für das Match angeben .
Umhüllen Sie dies mit einer Funktion:
import re
def normalize_whitespace(string):
return re.sub(r'(\s)\1{1,}', r'\1', string)
>>> normalize_whitespace('The fox jumped over the log.')
'The fox jumped over the log.'
>>> normalize_whitespace('First line\t\t\t \n\n\nSecond line')
'First line\t \nSecond line'
Eine Codezeile zum Entfernen aller zusätzlichen Leerzeichen vor, nach und innerhalb eines Satzes:
sentence = " The fox jumped over the log. "
sentence = ' '.join(filter(None,sentence.split(' ')))
Erläuterung:
* Die restlichen Elemente sollten Wörter oder Wörter mit Satzzeichen usw. sein. Ich habe dies nicht ausführlich getestet, aber dies sollte ein guter Ausgangspunkt sein. Alles Gute!
Lösung für Python-Entwickler:
import re
text1 = 'Python Exercises Are Challenging Exercises'
print("Original string: ", text1)
print("Without extra spaces: ", re.sub(' +', ' ', text1))
Ausgabe:
Original string: Python Exercises Are Challenging Exercises
Without extra spaces: Python Exercises Are Challenging Exercises
Das schnellste, was Sie für benutzergenerierte Zeichenfolgen erhalten können, ist:
if ' ' in text:
while ' ' in text:
text = text.replace(' ', ' ')
Der Kurzschluss macht es etwas schneller als die umfassende Antwort von Pythonlarry . Entscheiden Sie sich für diese Option, wenn Sie nach Effizienz streben und streng darauf bedacht sind, zusätzliche Leerzeichen der Single-Space-Variante auszusortieren .
Sehr überraschend - niemand hat eine einfache Funktion veröffentlicht, die viel schneller ist als ALLE anderen veröffentlichten Lösungen. Hier kommt's:
def compactSpaces(s):
os = ""
for c in s:
if c != " " or os[-1] != " ":
os += c
return os
Wenn es sich um Leerzeichen handelt, wird beim Teilen auf Keine keine leere Zeichenfolge in den zurückgegebenen Wert aufgenommen.
string = 'This is a string full of spaces and taps'
string = string.split(' ')
while '' in string:
string.remove('')
string = ' '.join(string)
print(string)
Ergebnisse :
Dies ist eine Zeichenfolge voller Leerzeichen und Taps
Verwenden Sie Folgendes, um Leerzeichen zu entfernen, indem Sie führende, nachfolgende und zusätzliche Leerzeichen zwischen den Wörtern berücksichtigen:
(?<=\s) +|^ +(?=\s)| (?= +[\n\0])
Der erste or
befasst sich mit dem führenden Leerraum, der zweite or
mit dem Beginn des String-führenden Leerraums und der letzte mit dem nachfolgenden Leerraum.
Zum Nachweis der Verwendung erhalten Sie über diesen Link einen Test.
https://regex101.com/r/meBYli/4
Dies ist mit der Funktion re.split zu verwenden.
Ich habe meine einfache Methode, die ich im College angewendet habe.
line = "I have a nice day."
end = 1000
while end != 0:
line.replace(" ", " ")
end -= 1
Dies ersetzt jedes doppelte Leerzeichen durch ein einzelnes Leerzeichen und führt dies 1000 Mal durch. Dies bedeutet, dass Sie 2000 zusätzliche Plätze haben können und trotzdem funktionieren. :) :)
Ich habe eine einfache Methode ohne Aufteilung:
a = "Lorem Ipsum Darum Diesrum!"
while True:
count = a.find(" ")
if count > 0:
a = a.replace(" ", " ")
count = a.find(" ")
continue
else:
break
print(a)
import re
Text = " You can select below trims for removing white space!! BR Aliakbar "
# trims all white spaces
print('Remove all space:',re.sub(r"\s+", "", Text), sep='')
# trims left space
print('Remove leading space:', re.sub(r"^\s+", "", Text), sep='')
# trims right space
print('Remove trailing spaces:', re.sub(r"\s+$", "", Text), sep='')
# trims both
print('Remove leading and trailing spaces:', re.sub(r"^\s+|\s+$", "", Text), sep='')
# replace more than one white space in the string with one white space
print('Remove more than one space:',re.sub(' +', ' ',Text), sep='')
Ergebnis:
Entfernen Sie den gesamten Platz: Sie können die folgenden Kanten auswählen, um Leerzeichen zu entfernen !! BRAliakbar Führenden Bereich entfernen: Sie können die folgenden Bereiche auswählen, um Leerzeichen zu entfernen !! BR Aliakbar Nachgestellte
Leerzeichen entfernen: Sie können unten Verkleidungen auswählen, um Leerzeichen zu entfernen !! BR Aliakbar Entfernen Sie führende und nachfolgende Leerzeichen: Sie können unten Verkleidungen auswählen, um Leerzeichen zu entfernen !! BR Aliakbar Entfernen Sie mehr als ein Leerzeichen: Sie können unten Verkleidungen auswählen, um Leerzeichen zu entfernen !! BR Aliakbar
Ich habe nicht viel in die anderen Beispiele gelesen, aber ich habe gerade diese Methode zum Konsolidieren mehrerer aufeinanderfolgender Leerzeichen erstellt.
Es werden keine Bibliotheken verwendet, und obwohl es in Bezug auf die Skriptlänge relativ lang ist, handelt es sich nicht um eine komplexe Implementierung:
def spaceMatcher(command):
"""
Function defined to consolidate multiple whitespace characters in
strings to a single space
"""
# Initiate index to flag if more than one consecutive character
iteration
space_match = 0
space_char = ""
for char in command:
if char == " ":
space_match += 1
space_char += " "
elif (char != " ") & (space_match > 1):
new_command = command.replace(space_char, " ")
space_match = 0
space_char = ""
elif char != " ":
space_match = 0
space_char = ""
return new_command
command = None
command = str(input("Please enter a command ->"))
print(spaceMatcher(command))
print(list(spaceMatcher(command)))