4
text = "Bob|19|01012017"
pat = re.compile("(?P<name>.+)|.*|(?P<bday>.+)") #hopefully this regex is correct
result = pat.match(text)
d = result.groupdict()
print d

What I get for d is:

{'bday': None, 'name': 'Bob|19|01012017'}

What I want is:

{bday: "01012017", name: "Bob"}

Can someone point out what I am doing wrong? I only need two fields for dict so I didn't write the age part.

Hanming Zeng
  • 337
  • 1
  • 4
  • 12

2 Answers2

13

You need to escape | to match literally otherwise the pattern is interpreted as or:

text = "Bob|19|01012017"
pat = re.compile("(?P<name>.+)\|.*\|(?P<bday>.+)") 
result = pat.match(text)
d = result.groupdict()

d
# {'bday': '01012017', 'name': 'Bob'}

A quick test against split method on the speed:

text = "Bob|19|01012017"
pat = re.compile("(?P<name>.+)\|.*\|(?P<bday>.+)")
​
def regex_to_dict(texts, pat):
    return [pat.match(text).groupdict() for text in texts]

regex_to_dict([text], pat)
# [{'bday': '01012017', 'name': 'Bob'}]

def split_to_dict(texts):
    dd = []
    for text in texts:
        name, _, bday = text.split('|')
        dd.append({'bday': bday, 'name': name})
    return dd

split_to_dict([text])
# [{'bday': '01012017', 'name': 'Bob'}]

texts = [text] * 100000

%timeit regex_to_dict(texts, pat)
# 10 loops, best of 3: 119 ms per loop

%timeit split_to_dict(texts)
# 10 loops, best of 3: 58.6 ms per loop
Psidom
  • 209,562
  • 33
  • 339
  • 356
1

For such simple case you may use simple str.split() approach:

text = "Bob|19|01012017"
items = text.split('|')
d = {'bday': items[-1], 'name': items[0]}

print(d)

The output:

{'name': 'Bob', 'bday': '01012017'}
RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105