pysnippets.lists.union_by
List union by a key
union_by(a: Iterable[T], b: Iterable[T], key: Callable[[T], K]) -> list[T]
Merge two lists, keeping the first item for each key, in a predictable order.
Merge two contact lists without duplicates, where two entries match when their emails match in any case.
union_by.py✓ ruff · mypy --strict
from collections.abc import Callable, Hashable, Iterable
from typing import TypeVar
T = TypeVar("T")
K = TypeVar("K", bound=Hashable)
def union_by(a: Iterable[T], b: Iterable[T], key: Callable[[T], K]) -> list[T]:
"""Merge ``a`` and ``b``, keeping the first item for each ``key``, in order."""
seen: set[K] = set()
merged = []
for items in (a, b):
for item in items:
k = key(item)
if k not in seen:
seen.add(k)
merged.append(item)
return merged- first one wins, so a beats b on a tie
examples✓ 3 doctests · 3.11–3.14
passed on Python 3.11 to 3.14: >>> from math import floorpassed on Python 3.11 to 3.14: >>> union_by([2.1], [1.2, 2.3], floor)[2.1, 1.2]passed on Python 3.11 to 3.14: >>> union_by(["Ada", "bob"], ["ADA", "Cy"], str.lower)['Ada', 'bob', 'Cy']Edit the function or the examples and run the doctests here, on Python 3.14. Python loads only when you click (about 7 MB, cached after the first time).
python 3.14 · in your browser
Loading Python 3.14 in your browser (≈7 MB, cached after the first time)…
Tab inserts four spaces. Press Escape, then Tab, to leave the editor. Control or Command plus Enter runs the examples.
How it works
- A set of seen keys decides whether each item is new.
- Items of
acome first, then the new items ofb, each in their original order. - Duplicates inside
aare dropped too.
Complexity: O(n + m) time, O(n + m) space
- 3.11✓passes
- 3.12✓passes
- 3.13✓passes
- 3.14✓passes
Import
from pysnippets.lists.union_by import union_byNo dependencies: copy union_by.py into your project, or clone the repo.Adapted from union-by in 30-seconds-of-python by the 30 seconds of code contributors, CC BY 4.0. Changed: Rewritten: deterministic order, first item wins; typed. Suggest an edit.