Supponiamo che questa stringa:
The fox jumped over the log.
Trasformandosi in:
The fox jumped over the log.
Qual è il più semplice (1-2 righe) per raggiungere questo obiettivo, senza dividere e andare in elenchi?
Supponiamo che questa stringa:
The fox jumped over the log.
Trasformandosi in:
The fox jumped over the log.
Qual è il più semplice (1-2 righe) per raggiungere questo obiettivo, senza dividere e andare in elenchi?
Risposte:
>>> import re
>>> re.sub(' +', ' ', 'The quick brown fox')
'The quick brown fox'
string.split
gestisce anche tutti i tipi di spazi bianchi.
re.sub(' {2,}', ' ', 'The quick brown fox')
per impedire sostituzioni ridondanti di spazio singolo con spazio singolo .
foo
è la tua stringa:
" ".join(foo.split())
Attenzione, questo rimuove "tutti i caratteri di spazi bianchi (spazio, tabulazione, riga nuova, ritorno, avanzamento del modulo )" (grazie a hhsaffar , vedere i commenti). Cioè, "this is \t a test\n"
finirà effettivamente come "this is a test"
.
import re
s = "The fox jumped over the log."
re.sub("\s\s+" , " ", s)
o
re.sub("\s\s+", " ", s)
poiché lo spazio prima della virgola è elencato come pipì di animali domestici in PEP 8 , come indicato dall'utente Martin Thoma nei commenti.
r"\s\s+"
modo che non provi a sostituire spazi già singoli.
"\s{2,}"
invece di una soluzione alternativa per non conoscere un comportamento regex moderatamente avanzato?
s
, ma restituisce il nuovo valore.
\s+
farebbe in modo che la riga leggesse "sostituisci uno o più spazi con uno spazio", anziché "sostituisci due o più spazi con uno spazio". Il primo mi fa immediatamente fermare e pensare "Perché sostituire uno spazio con uno spazio? È sciocco." Per me è un odore di codice (molto minore). Io in realtà non mi aspetto che ci sia alcuna differenza di prestazioni a tutti tra i due, come sta andando ad essere la copia in una nuova stringa in ogni caso, e deve fermarsi e test, a prescindere dal luogo in cui lo spazio viene copiato da .
\s\s+
perché questo non normalizzerà un personaggio TAB in uno spazio normale. una TABELLA SPAZIATRICE + viene sostituita in questo modo.
L'uso di regex con "\ s" e l'esecuzione di semplici string.split () rimuoverà anche altri spazi bianchi, come newline, ritorni a capo, tabulazioni. Se non lo si desidera, per fare solo più spazi , presento questi esempi.
Ho usato 11 paragrafi, 1000 parole, 6665 byte di Lorem Ipsum per ottenere prove del tempo realistiche e ho usato spazi extra di lunghezza casuale in tutto:
original_string = ''.join(word + (' ' * random.randint(1, 10)) for word in lorem_ipsum.split(' '))
Il one-liner essenzialmente farà una striscia di tutti gli spazi iniziali / finali e conserva uno spazio iniziale / finale (ma solo UNO ;-).
# 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
NOTA: la " Tenete a mente che il principale while
versione" ha creato una copia di original_string
, come credo una volta modificata alla prima esecuzione, le successive saranno più veloci (anche se solo per un po '). Man mano che questo aggiunge tempo, ho aggiunto questa copia di stringa alle altre due in modo che i tempi mostrassero la differenza solo nella logica. stmt
sui timeit
casi sarà eseguito solo una volta ; nel modo originale in cui l'ho fatto, il while
loop ha funzionato sulla stessa etichetta original_string
, quindi la seconda esecuzione non ci sarebbe stato nulla da fare. Il modo in cui è impostato ora, chiamando una funzione, usando due diverse etichette, non è un problema. Ho aggiunto assert
dichiarazioni a tutti i lavoratori per verificare che cambiamo qualcosa ogni iterazione (per coloro che potrebbero essere dubbiosi). Ad esempio, cambia in questo e si rompe:
# 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
Per la banale stringa, sembrerebbe che un while-loop sia il più veloce, seguito da Pythonic string-split / join e regex che tira su il retro.
Per stringhe non banali , sembra che ci sia un po 'di più da considerare. 32-bit 2.7? È regex in soccorso! 2.7 a 64 bit? Un while
loop è il migliore, con un margine decente. 32-bit 3.2, andare con il "corretto" join
. 64-bit 3.3, fare un while
giro. Ancora.
Alla fine, si può migliorare le prestazioni se / dove / quando necessario , ma è sempre meglio ricordare il mantra :
IANAL, YMMV, Caveat Emptor!
' '.join(the_string.split())
quanto questo è il solito caso d'uso, ma vorrei ringraziarti per il tuo lavoro!
' '.join(p for p in s.split(' ') if p)
<- persero ancora spazi di piombo / finali, ma rappresentavano più spazi. Per tenerli, deve fare come parts = s.split(' '); (' ' if not parts[0] else '') + ' '.join(p for p in s.split(' ') if p) + (' ' if not parts[-1] else '')
!
Sono d'accordo con il commento di Paul McGuire. Per me,
' '.join(the_string.split())
è di gran lunga preferibile estrarre una regex.
Le mie misurazioni (Linux e Python 2.5) mostrano che split-then-join è quasi cinque volte più veloce rispetto a "re.sub (...)", e ancora tre volte più veloce se precompilate regex una volta e fate l'operazione più volte. Ed è comunque più facile da capire - molto più Pythonic.
import re
string = re.sub('[ \t\n]+', ' ', 'The quick brown \n\n \t fox')
Ciò rimuoverà tutte le schede, le nuove linee e più spazi bianchi con un unico spazio bianco.
Ho provato il seguente metodo e funziona anche con il caso estremo come:
str1=' I live on earth '
' '.join(str1.split())
Ma se preferisci un'espressione regolare, puoi farlo come:
re.sub('\s+', ' ', str1)
Anche se è necessario eseguire una preelaborazione per rimuovere lo spazio finale e finale.
In alcuni casi è desiderabile sostituire le occorrenze consecutive di ogni carattere di spazio bianco con una singola istanza di quel carattere. Per fare ciò, useresti un'espressione regolare con riferimenti indietro.
(\s)\1{1,}
corrisponde a qualsiasi carattere di spazio bianco, seguito da una o più occorrenze di quel personaggio. Ora, tutto ciò che devi fare è specificare il primo gruppo ( \1
) come sostituto della partita.
Avvolgendolo in una funzione:
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'
Una riga di codice per rimuovere tutti gli spazi extra prima, dopo e all'interno di una frase:
sentence = " The fox jumped over the log. "
sentence = ' '.join(filter(None,sentence.split(' ')))
Spiegazione:
* Gli elementi rimanenti dovrebbero essere parole o parole con punteggiatura, ecc. Non l'ho verificato ampiamente, ma questo dovrebbe essere un buon punto di partenza. Ti auguro il meglio!
Soluzione per sviluppatori Python:
import re
text1 = 'Python Exercises Are Challenging Exercises'
print("Original string: ", text1)
print("Without extra spaces: ", re.sub(' +', ' ', text1))
Produzione:
Original string: Python Exercises Are Challenging Exercises
Without extra spaces: Python Exercises Are Challenging Exercises
Il più veloce che puoi ottenere per le stringhe generate dall'utente è:
if ' ' in text:
while ' ' in text:
text = text.replace(' ', ' ')
Il corto circuito lo rende leggermente più veloce della risposta completa di pythonlarry . Se vuoi l'efficienza, stai cercando di eliminare rigorosamente gli spazi bianchi della singola varietà di spazio .
Abbastanza sorprendente: nessuno ha pubblicato una funzione semplice che sarà molto più veloce di TUTTE le altre soluzioni pubblicate. Eccolo:
def compactSpaces(s):
os = ""
for c in s:
if c != " " or os[-1] != " ":
os += c
return os
Se si tratta di spazi bianchi, la divisione su Nessuno non includerà una stringa vuota nel valore restituito.
string = 'This is a string full of spaces and taps'
string = string.split(' ')
while '' in string:
string.remove('')
string = ' '.join(string)
print(string)
Risultati :
Questa è una stringa piena di spazi e rubinetti
Per rimuovere lo spazio bianco, considerando le aree iniziali, finali e extra tra le parole, utilizzare:
(?<=\s) +|^ +(?=\s)| (?= +[\n\0])
Il primo or
riguarda lo spazio bianco iniziale, il secondo or
riguarda l'inizio dello spazio bianco iniziale della stringa e l'ultimo riguarda lo spazio bianco finale.
Per la prova dell'uso, questo link ti fornirà un test.
https://regex101.com/r/meBYli/4
Questo deve essere usato con la funzione re.split .
Ho il mio metodo semplice che ho usato al college.
line = "I have a nice day."
end = 1000
while end != 0:
line.replace(" ", " ")
end -= 1
Questo sostituirà ogni doppio spazio con un singolo spazio e lo farà 1000 volte. Significa che puoi avere 2000 spazi extra e funzionerà comunque. :)
Ho un metodo semplice senza dividere:
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='')
Risultato:
Rimuovi tutto lo spazio: puoi selezionare lo spazio in basso per rimuovere lo spazio bianco !! BRAliakbar Rimuovi lo spazio iniziale: puoi selezionare i seguenti tagli per rimuovere lo spazio bianco !! BR Aliakbar
Rimuovi gli spazi finali: puoi selezionare i seguenti ritagli per rimuovere gli spazi bianchi !! BR Aliakbar Rimuovi spazi iniziali e finali: è possibile selezionare i seguenti tagli per rimuovere gli spazi bianchi !! BR Aliakbar Rimuovi più di uno spazio: è possibile selezionare i seguenti ritagli per rimuovere gli spazi bianchi !! BR Aliakbar
Non ho letto molto negli altri esempi, ma ho appena creato questo metodo per consolidare più caratteri spaziali consecutivi.
Non utilizza alcuna libreria e, sebbene sia relativamente lungo in termini di lunghezza degli script, non è un'implementazione complessa:
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)))