AlgoDaily

Grouping and Capturing

Read at your own pace. Code execution, quizzes, progress tracking, and the AI tutor are available in the interactive view with JavaScript enabled.

Why Groups Matter

From matching to extracting

In Anchors and Boundaries, you learned how to pin a match to the right location. Before that, Quantifiers and Alternation gave you control over how much and which alternatives can match.

Now we add a key regex skill: grouping and capturing.

Groups let you:

  • Treat several tokens as one unit
  • Extract only the part of a match you care about
  • Reuse matched text later in the same pattern
  • Build cleaner feature-extraction pipelines in Python

For an intermediate Python learner, this is where regex becomes less like search and more like structured parsing.

Why Groups Matter

Capturing With Parentheses

Parentheses create memory

A pair of parentheses (...) does two jobs:

  1. Groups a subpattern so regex treats it as one unit
  2. Captures the text matched by that subpattern

Python exposes captured text through the match object you met in Introduction to Regular Expressions.

In this example, the full match is the whole metric string, while each group extracts a useful field.

```python
import re

line = 'epoch=12 loss=0.084 accuracy=0.973'
pattern = r'epoch=(\d+) loss=([\d.]+)'

match = re.search(pattern, line)

print('Full match:', match.group(0))
print('Epoch:', match.group(1))
print('Loss:', match.group(2))
print('All captured groups:', match.groups())
```

Choose The Capture

You want to extract the numeric value from this text:

loss=0.084

Which pattern captures only 0.084 as group 1?

Group Numbering Rules

Groups count from left to right

Python numbers capturing groups by the order of their opening parentheses.

Important rules:

  • group(0) is always the entire match
  • group(1) is the first captured group
  • group(2) is the second captured group
  • Nested groups still count by opening parenthesis order

Example pattern:

((cat|dog)-(\d+))

Numbering:

((cat|dog)-(\d+))
12         3

So if the text is dog-42:

  • Group 0: dog-42
  • Group 1: dog-42
  • Group 2: dog
  • Group 3: 42

This matters when your pattern grows. A small extra pair of capturing parentheses can shift every later group number.

Group Numbering Rules

Group Index Check

In Python regex, after a successful match, match.group(__) returns the second captured group.

Fill in the blank: _____________

Named Captures

Prefer names when meaning matters

Numbered groups are compact, but they can become fragile as patterns evolve.

Python supports named capturing groups:

(?P<name>...)

This is especially useful in data-cleaning and machine-learning workflows, where extracted fields often become structured records or model features.

Instead of remembering whether confidence is group 2 or 3, you can ask for confidence directly.

```python
import re

line = 'prediction: label=cat confidence=0.97'
pattern = r'label=(?P<label>\w+) confidence=(?P<confidence>[\d.]+)'

match = re.search(pattern, line)

print('Label:', match.group('label'))
print('Confidence:', match.group('confidence'))
print('As dictionary:', match.groupdict())
```

Parentheses Always Change?

True or false: Adding parentheses around a subpattern always changes which text the regex matches.

Noncapturing Groups

Group without storing

Sometimes you need parentheses for structure, but you do not want a captured group.

Use a noncapturing group:

(?:...)

This is useful when combining tools from earlier lessons:

  • Group alternatives from Quantifiers and Alternation
  • Apply a quantifier to multiple tokens
  • Avoid shifting numbered capture groups

Compare:

(user|admin)-(\d+)      # captures role and id
(?:user|admin)-(\d+)    # captures only id

Both can match admin-42, but the second pattern keeps group numbering simpler.

Noncapturing Groups

Capture The Version

You have text like:

model-v2.7

You want group 1 to be exactly v2.7. Which pattern is best?

Extraction Workflow

Groups turn text into records

A strong practical pattern is:

  1. Write a regex that matches one complete record
  2. Capture the fields you need
  3. Convert each match into a Python dictionary

That gives you structured data that can feed validation scripts, analytics jobs, or ML preprocessing steps.

Next, we will add modifiers and lookaround tools that make these patterns more flexible without always consuming extra text.

```python
import re

text = '''
id=101 label=spam confidence=0.98
id=102 label=ham confidence=0.87
id=103 label=spam confidence=0.91
'''

pattern = re.compile(
    r'id=(?P<id>\d+)\s+label=(?P<label>\w+)\s+confidence=(?P<confidence>[\d.]+)'
)

records = []
for match in pattern.finditer(text):
    record = match.groupdict()
    record['id'] = int(record['id'])
    record['confidence'] = float(record['confidence'])
    records.append(record)

for record in records:
    print(record)
```
Open interactive view →