2009-08-13 19 views
5

ho una stringa di quel tipo di simile a questo:collasso spazi in una stringa

"stuff . // : /// more-stuff .. .. ...$%$% stuff -> DD" 

e voglio togliere tutta la punteggiatura, rendere tutto maiuscolo e comprimere tutti gli spazi in modo che assomiglia a questo:

"STUFF MORE STUFF STUFF DD" 

E 'possibile con una regex o devo combinare più di due? Questo è quello che ho finora:

def normalize(string): 
    import re 

    string = string.upper() 

    rex = re.compile(r'\W') 
    rex_s = re.compile(r'\s{2,}') 

    result = rex.sub(' ', string) # this produces a string with tons of whitespace padding 
    result = rex.sub('', result) # this reduces all those spaces 

    return result 

L'unica cosa che non funziona è lo spazio vuoto che crolla. Qualche idea?

risposta

15

Ecco un approccio single-step (ma il maiuscolo in realtà utilizza un metodo di stringa - molto più semplice!):

rex = re.compile(r'\W+') 
result = rex.sub(' ', strarg).upper() 

dove strarg è l'argomento stringa (Non nomi uso i moduli integrati shadow o i moduli libreria standard, , per favore).

+0

Sono d'accordo che questo sarebbe sicuramente il modo più semplice per affrontare il problema. – Amber

+1

Suppongo che dovrebbe essere "stringa" e non "risultato" nell'argomento di rex.sub? O è solo la sostituzione di parte del codice dell'utente? –

+1

@Brooks, hai ragione - sono così contrario a mettere in ombra i nomi dei moduli e dei moduli standard, che qualsiasi cosa mi sia sfuggita dalle corde. Fammi modificare per risolvere, e grazie! –

3
result = rex.sub(' ', string) # this produces a string with tons of whitespace padding 
result = rex.sub('', result) # this reduces all those spaces 

Perché si è digitato e si è dimenticato di utilizzare rex_s per la seconda chiamata. Inoltre, è necessario sostituire almeno uno spazio indietro o finire con qualsiasi spazio vuoto multiplo che non diventi affatto spazio, invece di uno spazio vuoto singolo.

result = rex.sub(' ', string) # this produces a string with tons of whitespace padding 
result = rex_s.sub(' ', result) # this reduces all those spaces 
+0

buona pesca da parte tipo. Ho appena notato che momenti dopo la pubblicazione. Mi hai battuto prima che avessi la possibilità di modificare OMG – priestc

+0

Ti suggerirei di dare un'occhiata al codice di Alex - è un modo molto più conciso di affrontare il problema, e gestisce anche la punteggiatura/spazio bianco alla fine della stringa. – Amber

1

Devi utilizzare le espressioni regolari? Pensi di doverlo fare in una sola riga?

>>> import string 
>>> s = "stuff . // : /// more-stuff .. .. ...$%$% stuff -> DD" 
>>> s2 = ''.join(c for c in s if c in string.letters + ' ') 
>>> ' '.join(s2.split()) 
'stuff morestuff stuff DD' 
3
s = "$$$aa1bb2 cc-dd ee_ff ggg." 
re.sub(r'\W+', ' ', s).upper() 
# ' AA1BB2 CC DD EE_FF GGG ' 

Is _ punteggiatura?

re.sub(r'[_\W]+', ' ', s).upper() 
# ' AA1BB2 CC DD EE FF GGG ' 

Non vuoi lo spazio iniziale e finale?

re.sub(r'[_\W]+', ' ', s).strip().upper() 
# 'AA1BB2 CC DD EE FF GGG' 
+0

+1 Per aggirare il passaggio 're.compile (...)'. Se potessi, ti darei un altro +1 per sottolineare anche la questione di come gestire "_" e il WS iniziale/finale, poiché queste cose sono spesso trascurate con espressioni regolari. –

1

funziona in python3 questo manterrà lo stesso carattere di spazio vuoto che è stato compresso. Quindi, se hai una scheda e uno spazio uno accanto all'altro, non collideranno in un singolo personaggio.

def collapse_whitespace_characters(raw_text): 
    ret = '' 
    if len(raw_text) > 1: 
     prev_char = raw_text[0] 
     ret += prev_char 
     for cur_char in raw_text[1:]: 
      if not cur_char.isspace() or cur_char != prev_char: 
       ret += cur_char 
      prev_char = cur_char 
    else: 
     ret = raw_text 
    return ret 

questo crollerà set spazio bianco nel primo carattere di spazio bianco che vede

def collapse_whitespace(raw_text): 
    ret = '' 
    if len(raw_text) > 1: 
     prev_char = raw_text[0] 
     ret += prev_char 
     for cur_char in raw_text[1:]: 
      if not cur_char.isspace() or \ 
        (cur_char.isspace() and not prev_char.isspace()): 
       ret += cur_char 
      prev_char = cur_char 
    else: 
     ret = raw_text 
    return ret 

> > > collapse_whitespace_characters ('abbiamo   come         spazi     e \ t \ t   TABS       E   WHATEVER \ xa0 \ xa0IS ')
'ci piace spazi e \ t TAB \ tand QUALSIASI \ xa0IS'

> > > collapse_whitespace ('abbiamo   come         spazi     e \ t \ t   COMPRESSE       E   QUALSIASI \ xA0 \ xa0IS ')
'ci piace spazi e \ tTABS \ tand QUALSIASI \ xa0IS'

per la punteggiatura

def collapse_punctuation(raw_text): 
    ret = '' 
    if len(raw_text) > 1: 
     prev_char = raw_text[0] 
     ret += prev_char 
     for cur_char in raw_text[1:]: 
      if cur_char.isalnum() or cur_char != prev_char: 
       ret += cur_char 
      prev_char = cur_char 
    else: 
     ret = raw_text 
    return ret 

per rispondere alla domanda in realtà

orig = 'stuff . // : /// more-stuff .. .. ...$%$% stuff -> DD' 
collapse_whitespace(''.join([(c.upper() if c.isalnum() else ' ') for c in orig])) 

come detto, l'espressione regolare sarebbe qualcosa di simile

re.sub('\W+', ' ', orig).upper() 
Problemi correlati