Python no té una funció específica per eliminar espais superflus (és a dir, eliminar tots els espais del principi i del final d’un text, i entre paraules deixar-hi només un espai).
Hi ha una manera molt pythònica de fer-ho:
" ".join(text_amb_espais.split())
I això és ràpid? Doncs comparem 3 alternatives amb timeit:
- Aquesta de join i split
- Un bucle pas a pas: mirar caràcter a caràcter si hauríem de posar-lo al resultat final, depenent de si aquest o l’anterior són espais.
- Amb tantes substitucions com calgui de dos espais seguits a un.
El codi per mesurar-ho és:
from timeit import timeit
def eliminar_espais_split_join (text: str) -> str:
return " ".join(text.split())
def eliminar_espais_posicio_a_posicio (text: str) -> str:
anterior_es_espai = True
sense_espais_redundants = ""
for x in text:
if x == " ":
if not anterior_es_espai:
sense_espais_redundants += x
anterior_es_espai = True
else:
sense_espais_redundants += x
anterior_es_espai = False
if len(sense_espais_redundants) > 0:
if sense_espais_redundants [-1] == " ":
sense_espais_redundants = sense_espais_redundants[:-1]
return sense_espais_redundants
def eliminar_espais_replace (text: str) -> str:
r2 = text
while (r1:= r2.replace(" ", " ")) != r2:
r2 = r1
if len(r2) > 0:
if r2[0] == " ":
r2 = r2[1:]
if len(r2) > 0:
if r2[-1] == " ":
r2 = r2[:-1]
return r2
TEXT_PROVA = " Vivamus quis lacus quis sapien elementum finibus et sollicitudin nisi. "
assert (eliminar_espais_posicio_a_posicio (TEXT_PROVA) == eliminar_espais_split_join(TEXT_PROVA))
assert (eliminar_espais_replace (TEXT_PROVA) == eliminar_espais_split_join(TEXT_PROVA))
EXECUCIONS = 100_000
temps = (timeit (lambda: eliminar_espais_split_join (TEXT_PROVA), number=EXECUCIONS),
timeit (lambda: eliminar_espais_posicio_a_posicio (TEXT_PROVA), number=EXECUCIONS),
timeit (lambda: eliminar_espais_replace(TEXT_PROVA), number=EXECUCIONS))
temps_minim = min(temps)
print (f"eliminar_espais_split_join: {temps [0] / temps_minim:.2f} vegades el mínim")
print (f"eliminar_espais_posicio_a_posicio: {temps [1] / temps_minim:.2f} vegades el mínim")
print (f"eliminar_espais_replace: {temps [2] / temps_minim:.2f} vegades el mínim")
I el resultat:
eliminar_espais_split_join: 1.00 vegades el mínim
eliminar_espais_replace: 2.25 vegades el mínim
eliminar_espais_posicio_a_posicio: 8.83 vegades el mínim
He provat algunes variants, sense que influeixin significativament en els resultats:
- Sense fer servir l’operador walrus (notació := al while) a eliminar_espais_replace.
- Amb substitucions de 2 i 3 espais concatenades a eliminar_espais_replace.
- Amb un índex per accedir als diferents caràcters a posicio_a_posicio.
O sigui, he deixat l’split_join al codi, la manera més genuïna del Python és alhora la més ràpida.