2010-08-02 5 views
3

J'ai besoin d'analyser les jetons de temps d'une chaîne où les jetons sont optionnels. Les échantillons donnés:Extraction de jetons dont certains sont optionnels

  • tt-5d10h
  • tt-5d10h30m
  • tt-5d30m
  • tt-10h30m
  • tt-5d
  • tt-10h
  • tt-30m

Comment puis-je, en Python, analyser cela de préférence comme l'ensemble (jours, heures, minutes)?

Répondre

4

Ce programme retourne trois entiers (jours, heures, secondes) pour chaque entrée:

import re 
samples = ['tt-5d10h', 'tt-5d10h30m', 'tt-5d30m', 'tt-10h30m', 'tt-5d', 'tt-10h', 'tt-30m',] 

def parse(text): 
    match = re.match('tt-(?:(\d+)d)?(?:(\d+)h)?(?:(\d+)m)?', text) 
    values = [int(x) for x in match.groups(0)] 
    return values 

for sample in samples: 
    print parse(sample) 

Sortie:

[5, 10, 0] 
[5, 10, 30] 
[5, 0, 30] 
[0, 10, 30] 
[5, 0, 0] 
[0, 10, 0] 
[0, 0, 30] 
+0

Plus rapide :) ... +1 – chryss

2
>>> pattern = re.compile("tt-(\d+d)?(\d+h)?(\d+m)?") 
>>> results = pattern.match("tt-5d10h") 
>>> days, hours, minutes = results.groups() 
>>> days, hours, minutes 
('5d', '10h', None) 
1

similaires à la réponse de Compie, mais rendant le résultat final plus agréable à traiter avec:

re.match('tt-(?:(?P<days>\d+)d)?(?:(?P<hours>\d+)h)?(?:(?P<minutes>\d+)m)?', text).groupdict() 

Exemple:

>>> import re 
>>> s = ['tt-5d10h', 'tt-5d10h30m', 'tt-5d30m', 'tt-10h30m', 'tt-5d', 'tt-10h', 'tt-30m'] 
>>> for text in s: 
    print(re.match('tt-(?:(?P<days>\d+)d)?(?:(?P<hours>\d+)h)?(?:(?P<minutes>\d+)m)?', text).groupdict()) 

{'hours': '10', 'minutes': None, 'days': '5'} 
{'hours': '10', 'minutes': '30', 'days': '5'} 
{'hours': None, 'minutes': '30', 'days': '5'} 
{'hours': '10', 'minutes': '30', 'days': None} 
{'hours': None, 'minutes': None, 'days': '5'} 
{'hours': '10', 'minutes': None, 'days': None} 
{'hours': None, 'minutes': '30', 'days': None} 

Si vous voulez remplacer 0 pour les jetons de gauche à la place, il suffit d'utiliser groupdict(0) au lieu de groupdict().

1

Par partition:

inputstring="""tt-5d10h 
tt-5d10h30m 
tt-5d30m 
tt-10h30m 
tt-5d 
tt-10h 
tt-30m 
""" 
separators=('d','h','m') 
result=[] 
for text in (item.lstrip('t-') for item in inputstring.splitlines()): 
    data=[] 
    for sep in separators: 
     d,found,text = text.partition(sep) 
     if found: data.append(int(d.rstrip(sep))) 
     else: 
      data.append(0) 
      text=d 
    result.append(data) 
# show input and result 
for respairs in zip(inputstring.splitlines(),result): print(respairs) 
""" Output: 
('tt-5d10h', [5, 10, 0]) 
('tt-5d10h30m', [5, 10, 30]) 
('tt-5d30m', [5, 0, 30]) 
('tt-10h30m', [0, 10, 30]) 
('tt-5d', [5, 0, 0]) 
('tt-10h', [0, 10, 0]) 
('tt-30m', [0, 0, 30]) 
""" 
1

est ici une approche pyparsing à votre problème:

tests = """tt-5d10h 
tt-5d10h30m 
tt-5d30m 
tt-10h30m 
tt-5d 
tt-10h 
tt-30m""".splitlines() 

from pyparsing import Word,nums,Optional 

integer = Word(nums).setParseAction(lambda t:int(t[0])) 

timeFormat = "tt-" + (
       Optional(integer("days") + "d") + 
       Optional(integer("hrs") + "h") + 
       Optional(integer("mins") + "m") 
       ) 

def normalizeTime(tokens): 
    return tuple(tokens[field] if field in tokens else 0 
       for field in "days hrs mins".split()) 

timeFormat.setParseAction(normalizeTime) 

for test in tests: 
    print "%-12s ->" % test, 
    print "%d %02d:%02d" % timeFormat.parseString(test)[0] 

Prints:

tt-5d10h  -> 5 10:00 
tt-5d10h30m -> 5 10:30 
tt-5d30m  -> 5 00:30 
tt-10h30m -> 0 10:30 
tt-5d  -> 5 00:00 
tt-10h  -> 0 10:00 
tt-30m  -> 0 00:30 

Ou pour préserver les résultats nommés:

def normalizeTime(tokens): 
    for field in "days hrs mins".split(): 
     if field not in tokens: 
      tokens[field] = 0 

timeFormat.setParseAction(normalizeTime) 

for test in tests: 
    print "%-12s ->" % test, 
    print "%(days)d %(hrs)02d:%(mins)02d" % timeFormat.parseString(test) 
Questions connexes