# Grouping & Selection

Use `group()` and `select()` to combine multiple elements or pick specific pads
before connecting.

## Grouping Elements

`group()` combines multiple elements so `connect()` sees all their pads as one
unit:

```python
from sgn import Pipeline, IterSource, NullSink
from sgn.groups import group

src1 = IterSource(name="s1", source_pad_names=["H1"], iters={"H1": [1, 2]})
src2 = IterSource(name="s2", source_pad_names=["L1"], iters={"L1": [3, 4]})

snk1 = NullSink(name="k1", sink_pad_names=["H1"])
snk2 = NullSink(name="k2", sink_pad_names=["L1"])

p = Pipeline()
p.connect(group(src1, src2), group(snk1, snk2))  # H1->H1, L1->L1
p.run()
```

## Selecting Pads

`select()` narrows an element to specific pads, ignoring the rest:

```python
from sgn import Pipeline, IterSource, NullSink
from sgn.groups import select

src = IterSource(
    name="src",
    source_pad_names=["H1", "L1", "V1"],
    iters={"H1": [1], "L1": [2], "V1": [3]},
)

snk = NullSink(name="snk", sink_pad_names=["H1", "L1"])

p = Pipeline()
p.connect(select(src, "H1", "L1"), snk)  # V1 is excluded
```

## Combining Group and Select

Mix `group()` and `select()` for complex topologies:

```{.python notest}
from sgn import Pipeline, IterSource, NullSink
from sgn.groups import group, select

dedicated = IterSource(name="ded", source_pad_names=["H1"], iters={"H1": [1]})
multi = IterSource(
    name="multi",
    source_pad_names=["L1", "V1"],
    iters={"L1": [2], "V1": [3]},
)

snk_h1 = NullSink(name="sh", sink_pad_names=["H1"])
snk_l1 = NullSink(name="sl", sink_pad_names=["L1"])

sources = group(dedicated, select(multi, "L1"))  # H1 + L1 only
sinks = group(snk_h1, snk_l1)

p = Pipeline()
p.connect(sources, sinks)
p.run()
```

## Explicit Linking with Groups

When automatic matching doesn't work, add a `link_map`:

```python
from sgn import Pipeline, IterSource, NullSink
from sgn.groups import group

src1 = IterSource(name="s1", source_pad_names=["out_a"], iters={"out_a": [1]})
src2 = IterSource(name="s2", source_pad_names=["out_b"], iters={"out_b": [2]})

snk1 = NullSink(name="k1", sink_pad_names=["in_x"])
snk2 = NullSink(name="k2", sink_pad_names=["in_y"])

p = Pipeline()
p.connect(
    group(src1, src2),
    group(snk1, snk2),
    link_map={"in_x": "out_a", "in_y": "out_b"},
)
p.run()
```

## Iterating Over Pads

Use `select_by_source()` or `select_by_sink()` to iterate over individual pads
in a group or selection, yielding one `PadSelection` per pad:

```{.python notest}
sources = group(src1, src2)

for pad_name, pad_selection in sources.select_by_source():
    pipeline.connect(pad_selection, some_sink)
```
