2015-04-30 16 views
6

Mam problem odłogowania, Im powinien uzyskać dane wejściowe użytkownika w postaci 10:10:10 (hh: mm: ss) lub 10:10 (mm: ss) lub 10 (SS). Teraz potrzebuję sprawdzić parametry odłogowania:Python: sprawdzania poprawności danych wejściowych Czas

  • Jeśli otrzymam tylko sekundy, to nie ma limitu.
  • Jeśli otrzymam mm:ss, sekundy są ograniczone do 0..59, a minuty są nieograniczone.
  • Jeśli otrzymuję numer hh:mm:ss, zarówno sekundy, jak i minuty są ograniczone do 0..59, podczas gdy godziny są nieograniczone.

Następnie należy zwrócić obiekt TimeDelta.

Naiwnym sposobem jest napisanie wielu instrukcji if, aby to sprawdzić. Ale ja szukam gładszej drodze.

val = "11:66:11" 
try: 
    val = map(int, val.split(':')) 
except ValueError: 
    return False 
if len(val) == 1: 
    return val 
if len(val) == 2: 
    if val[1] > 59: 
     print "Bad seconds" 
     return False 
if len(val) == 3: 
    if val[2] > 59 or val[1] >59: 
     print "Bad seconds/minutes" 
     return False 
while len(val) < 3: 
     split.insert(0,0) 
return = timedelta(hours=split[0],minutes=split[1],seconds=split[2]) 
+0

Masz błąd? Z jakim problemem stoisz? – Nilesh

+0

Bez błędów, kod, który napisałem, jest natywnym sposobem robienia tego, co chcę. Proszę o bardziej płynny sposób. Bardziej pytonowo. – MichaelR

Odpowiedz

7

Jak o użyciu wyrażenia regularnego tutaj:

import re 
import datetime 
pattern = re.compile(r'^(\d+)(?::([0-5]?\d)(?::([0-5]?\d))?)?$') 

def str2seconds(val): 
    match = pattern.match(val) 
    if not match: 
     raise ValueError("Invalid input: %s" % val) 
    else: 
     result = 0 
     for i in match.groups(): 
      if i is not None: 
       result *= 60 
       result += int(i) 

    return datetime.timedelta(seconds=result) 

Przykład:

>>> print(str2seconds('255')) 
0:04:15 
>>> print(str2seconds('255:25')) 
4:15:25 
>>> print(str2seconds('255:25:25')) 
10 days, 15:25:25 
>>> print(str2seconds('255:25:25:255')) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "y.py", line 8, in str2seconds 
    raise ValueError("Invalid input: %s" % val) 
ValueError: Invalid input: 255:25:25:255 
>>> print(str2seconds('255:25:60')) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "y.py", line 8, in str2seconds 
    raise ValueError("Invalid input: %s" % val) 
ValueError: Invalid input: 255:25:60 

Regularne część wyrażenie przez część:

  • ^: zaczynając od ciąg
  • (\d+): 1-n cyfr, złapanych w grupie 1
  • (?::([0-5]?\d)(?::([0-5]?\d))?)? opcjonalna część:
    • (?:...) jest non-Przechwytywanie grupie
    • : mecze dosłownym :
    • ([0-5]?\d) się opcjonalna cyfra 0-5, a następnie cyfra uchwycona jako grupa 2
    • w pierwszej kolejności znajduje się druga grupa niezapisywana t: (?::([0-5]?\d))?, który opcjonalnie pasuje do drugiego :, po którym następuje , opcjonalna cyfra 0-5, po której następuje cyfra; i przechwycenie cyfr w grupie 3
    • i ostatecznie $ dopasowuje koniec napisu. Ściśle, ^ na początku nie jest konieczne, ponieważ match zakotwicza dopasowanie na początku; jednak konieczny jest $, w przeciwnym razie dopasowanie nie jest zakotwiczone na końcu struny! (Python 3.4 dodaje the re.fullmatch aby rozwiązać ten problem.)

match.groups() będzie krotka 3 sztuk; nie pasujące grupy zostaną zwrócone jako None.

+0

Działa jak urok!Czy możesz wyjaśnić wyrażenie regularne? Próbowałem to zrozumieć, ale utknąłem. – MichaelR

+0

Jeśli spróbujesz rozwiązać problem za pomocą wyrażeń regularnych, bardzo często masz dwa problemy. Myślę, że bardziej podstawowa analiza ciągów jest bardziej odpowiednia. – bgusach

+0

@ ikaros45 zły żart –

Powiązane problemy