2012-12-02 17 views
10

Sto analizzando alcuni dati in cui il formato standard è qualcosa come 10 pizzas. A volte, i dati vengono immessi correttamente e potremmo finire con 5pizzas anziché 5 pizzas. In questo scenario, voglio analizzare il numero di pizze.Divisione di una stringa in cui passa tra caratteri numerici e alfabetici

Il modo ingenuo di fare questo sarebbe quello di controllare carattere per carattere, costruendo una stringa fino a raggiungere un non-cifra e quindi a quella stringa come un numero intero.

num_pizzas = "" 
for character in data_input: 
    if character.isdigit(): 
     num_pizzas += character 
    else: 
     break 
num_pizzas = int(num_pizzas) 

Questo è piuttosto goffo, però. C'è un modo più semplice per dividere una stringa in cui passa da cifre numeriche a caratteri alfabetici?

risposta

15

chiedete un modo per dividere una stringa su cifre, ma poi nel tuo esempio, quello che realmente vuole è solo il primo numero, questo fatto facilmente con itertools.takewhile():

>>> int("".join(itertools.takewhile(str.isdigit, "10pizzas"))) 
10 

Questo rende un sacco di senso - quello che stiamo facendo è prendere il personaggio dalla stringa mentre sono cifre. Questo ha il vantaggio di interrompere l'elaborazione non appena arriviamo al primo carattere non numerico.

Se è necessario anche i dati più tardi, allora quello che stai cercando è itertools.groupby() mescolato con un semplice list comprehension:

>>> ["".join(x) for _, x in itertools.groupby("dfsd98sd8f68as7df56", key=str.isdigit)] 
['dfsd', '98', 'sd', '8', 'f', '68', 'as', '7', 'df', '56'] 

Se poi si vuole fare un numero gigantesco:

>>> int("".join("".join(x) for is_number, x in itertools.groupby("dfsd98sd8f68as7df56", key=str.isdigit) if is_number is True)) 
98868756 
1

Che ne dici di un'espressione regolare?

reg = re.compile(r'(?P<numbers>\d*)(?P<rest>.*)') 
result = reg.search(str) 
if result: 
    numbers = result.group('numbers') 
    rest = result.group('rest') 
11

per dividere la stringa in cifre è possibile utilizzare re.split con l'espressione regolare \d+:

>>> import re 
>>> def my_split(s): 
    return filter(None, re.split(r'(\d+)', s)) 

>>> my_split('5pizzas') 
['5', 'pizzas'] 
>>> my_split('foo123bar') 
['foo', '123', 'bar'] 

per trovare il primo impiego numero di re.search:

>>> re.search('\d+', '5pizzas').group() 
'5' 
>>> re.search('\d+', 'foo123bar').group() 
'123' 

Se si conosce il numero deve essere all'inizio della stringa, quindi è possibile utilizzare re.match anziché re.search. Se si desidera trovare tutti i numeri e scartare il resto è possibile utilizzare re.findall.

Problemi correlati