2009-08-13 17 views
5

Mam ciąg znaków, który rodzaj wygląda następująco:zawaleniem spacje w ciągu znaków

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

i chcę zdejmować wszystkie znaki interpunkcyjne, zrobić wszystko wielkie i zwinąć wszystkie białe znaki tak, że wygląda tak:

"STUFF MORE STUFF STUFF DD" 

Czy jest to możliwe z jednym wyrażeniem regularnym lub czy muszę połączyć więcej niż dwa? Oto, co mam do tej pory:

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 

Jedyne, co nie działa, to zawalenie białych znaków. Jakieś pomysły?

Odpowiedz

15

Oto podejście jednoetapowe (ale uppercasing rzeczywiście wykorzystuje metodę String - znacznie prostsze!):

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

gdzie strarg jest argument ciąg (zrobić nie nazwy użytku wbudowane moduły cieni lub standardowe moduły biblioteczne, , proszę).

+0

Zgadzam się, że z pewnością byłby to prostszy sposób podejścia do problemu. – Amber

+1

Zakładam, że powinno to być "string", a nie "result" w argumencie rex.sub? Czy to tylko zastępuje część kodu użytkownika? –

+1

@ Brooks, masz rację - jestem tak niechętny wbudowanym shadowingom i standardowym nazwom modułów, że cokolwiek BUT string wyleciało mi z palców. Pozwól mi edytować, aby naprawić i dzięki! –

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

Ponieważ zamiast tego wpisałeś i zapomniałeś użyć rex_s do drugiego połączenia. Musisz też zastąpić co najmniej jedną spację lub skończysz z luką wieloprzestrzenną, która nie będzie wcale luką, a nie pojedynczą przestrzenią.

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

dobrego połowu na strony typu. Właśnie zauważyłem, że chwile po wysłaniu. pokonałeś mnie, zanim miałem okazję edytować OMG – priestc

+0

Sugeruję przyjrzenie się kodowi Alexa - jest to o wiele bardziej zwięzły sposób podejścia do problemu, a także ładnie traktuje interpunkcję/spacje na końcu łańcucha. – Amber

1

Czy musisz używać wyrażeń regularnych? Czy uważasz, że musisz to zrobić w jednym wierszu?

>>> 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 ' 

Czy _ znaki interpunkcyjne?

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

Nie chcesz przestrzeni początkowej i końcowej?

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

+1 Do ominięcia kroku 're.compile (...)'. Gdybym mógł, dałbym ci jeszcze +1 za wskazanie również, jak sobie poradzić z "_" i prowadzącymi/spychającymi WS, ponieważ takie rzeczy są tak często pomijane przez regex. –

1

działa w python3 to zachowa ten sam znak odstępu, który zawaliłeś. Więc jeśli masz zakładkę i spację obok siebie, nie zwiniesz w jeden znak.

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 

ten załamie whitespace zestawy do pierwszej spacją widzi

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 ("my   jak         przestrzenie     i \ t \ t   JOT       I   WHATEVER \ xa0 \ xa0IS ')
'lubimy przestrzenie i \ t TABS \ TAND COKOLWIEK \ xa0IS'

> > > collapse_whitespace ("my   jak         przestrzeniach     i \ t \ t   TABS       I   COKOLWIEK \ xa0 \ xa0IS ')
'lubimy przestrzenie i \ tTABS \ tAND COKOLWIEK \ xa0IS'

dla interpunkcji

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 

faktycznie odpowiedzieć na pytanie

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

jak powiedziałem, regexp byłoby coś

re.sub('\W+', ' ', orig).upper() 
Powiązane problemy