Gathering attendance list with python re.findall

Viewed 77

Here we have a zoom chat history from which I would like to extract all of the student ID, for example, 38150002, and the name of the ID owner (e.g. smith example).

17:00:44     From Smith Example : 38150002 Smith Example
17:00:54     From Smith Example : 41050002 Smith Middle Example
17:01:04     From Smith Example : 37-191129 Smith One Example
17:01:12     From Smith Example : 31-086612 Smith Example
17:01:20     From Smith Example : 40-250233 Smith Example
17:01:33     From Smith Example : 38129055 Smith Example
17:01:39     From Smith Example : 38-129055 Smith Example Joe

I succeed to extract the student id with a set pattern with re.findall.

lst = re.findall('\d\d-\d+', ex) #for id like 40-250233

The question is how can I extract the name following the student id?

4 Answers

Assuming the exact structure you gave, you can use this regex:

\d\d:\d\d:\d\d.*:\s*([\d-]+)\s*(.*)$

I put the ID and name in capture groups so using findall will give a nice result. For example:

import re

s = """17:00:44     From Smith Example : 38150002 Smith Example\n
17:00:54     From Smith Example : 41050002 Smith Middle Example\n
17:01:04     From Smith Example : 37-191129 Smith One Example\n
17:01:12     From Smith Example : 31-086612 Smith Example\n
17:01:20     From Smith Example : 40-250233 Smith Example\n
17:01:33     From Smith Example : 38129055 Smith Example\n
17:01:39     From Smith Example : 38-129055 Smith Example Joe\n"""

print(re.findall(r'\d\d:\d\d:\d\d.*:\s*([\d-]+)\s*(.*)$', s, re.M))

will give:

[('38150002', 'Smith Example'), 
 ('41050002', 'Smith Middle Example'), 
 ('37-191129', 'Smith One Example'), 
 ('31-086612', 'Smith Example'), 
 ('40-250233', 'Smith Example'), 
 ('38129055', 'Smith Example'), 
 ('38-129055', 'Smith Example Joe')]

Regex Demo here.


Note that if you are iterating a file line by line you don't need the re.M flag.

Use the following to extract the ID and name (feel free to refine the name-matching regex \w+(?:[ ]\w+)+ for better control):

>>> re.findall('\d\d-\d+[ ]\w+(?:[ ]\w+)+', ex)
['37-191129 Smith One Example', '31-086612 Smith Example', '40-250233 Smith Example', '38-129055 Smith Example Joe']

If you only want the name, use the non-capturing group (?:) to omit the ID part and put the name in ():

>>> re.findall('(?:\d\d-\d+)[ ](\w+(?:[ ]\w+)+)', ex)
['Smith One Example', 'Smith Example', 'Smith Example', 'Smith Example Joe']

BTW you can also capture ID and name as tuple:

>>> re.findall('(\d\d-\d+)[ ](\w+(?:[ ]\w+)+)', ex)
[('37-191129', 'Smith One Example'), ('31-086612', 'Smith Example'), ('40-250233', 'Smith Example'), ('38-129055', 'Smith Example Joe')]

There are alot of ways, but here's an easy one using split and join, which assumes that:

  1. Colons remain constant as separators in the file
  2. Everything after the student ID refers to the student name

The code is as follows, applied to one row:

row_string = "17:00:44     From Smith Example : 38150002 Smith Example"
ID = row_string.split(':')[3].split(' ')[1] # '38150002'
name = " ".join(row_string.split(':')[3].split(' ')[2:]) #'Smith Example' 

Input:

ex='''17:00:44     From Smith Example : 38150002 Smith Example
17:00:54     From Smith Example : 41050002 Smith Middle Example
17:01:04     From Smith Example : 37-191129 Smith One Example
17:01:12     From Smith Example : 31-086612 Smith Example
17:01:20     From Smith Example : 40-250233 Smith Example
17:01:33     From Smith Example : 38129055 Smith Example
17:01:39     From Smith Example : 38-129055 Smith Example Joe'''

lst = re.findall(r'(:\s+)(\d{2}-\d+|\d+)([\s+\w+]+)', ex)

print(lst)

Ouput :

[(': ', '38150002', ' Smith Example\n17'), (': ', '41050002', ' Smith Middle Example\n17'), (': ', '37-191129', ' Smith One Example\n17'), (': ', '31-086612', ' Smith Example\n17'), (': ', '40-250233', ' Smith Example\n17'), (': ', '38129055', ' Smith Example\n17'), (': ', '38-129055', ' Smith Example Joe')]

Here you can get both patterns matched for the examples you have given . The output basically contains 3 parts for each pattern matched - first part is : , second part is ID which is the 2 patterns you have given (if you want to match more patterns you should change the regex as per needs , cannot write a regex in generic way) , third part is whole string after ID (this also should be customized if you want to capture only upto 2nd space or 3rd space character)

Related