Skip to content

Instantly share code, notes, and snippets.

@hjwp
Last active October 24, 2023 22:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hjwp/caac23f8d6717dec81ddd9d116c49696 to your computer and use it in GitHub Desktop.
Save hjwp/caac23f8d6717dec81ddd9d116c49696 to your computer and use it in GitHub Desktop.
A few examples of problems solved with reduce vs more "traditional" (pythonic?) ways
vehicles = [
{"category": "Cars", "id": "Audi"},
{"category": "Cars", "id": "Mercedes"},
{"category": "Motorbikes", "id": "Ducati"}
]
expected = {
"Cars": ["Audi", "Mercedes"],
"Motorbikes": ["Ducati"],
}
def by_category_pythonic(vehicles: list[dict[str, str]]) -> dict[str, list[str]]:
categories = {v["category"] for v in vehicles}
return {
category: [v["id"] for v in vehicles if v["category"] == category]
for category in categories
}
def by_category_reduce(vehicles: list[dict[str, str]]) -> dict[str, list[str]]:
import functools
return functools.reduce(
lambda acc, v: acc | {v["category"]: acc.get(v["category"], []) + [v["id"]]},
vehicles,
{},
)
"""
clojure version:
(reduce (fn [acc {:keys [category id]}]
(update acc category conj {:id id}))
{}
vehicles)
"""
def test_it_works_1():
assert by_category_pythonic(vehicles) == expected
def test_it_works_with_reduce():
assert by_category_reduce(vehicles) == expected
import functools
src = [
{"town": "London"},
{"city": "New York", "name": "Geoff"},
{"city": "London", "town": "Islington"},
{"city": "Shanghai", "town": "Shanghai"},
]
expected = {"London", "New York", "Islington", "Shanghai"}
def to_set_reduce(info: list[dict[str, str]]) -> set[str]:
return set(
filter(
None,
functools.reduce(
lambda acc, d: acc | {d.get("city"), d.get("town")}, info, set()
),
)
)
def to_set_pythonic(info: list[dict[str, str]]) -> set[str]:
return {x for d in info for x in [d.get("city"), d.get("town")] if x is not None}
def test_it_works_pythonic():
assert to_set_pythonic(src) == expected
def test_it_works_with_reduce():
assert to_set_reduce(src) == expected
import functools
import typing
things = ["red", "blue", "red", "green", "blue", "blue"]
expected = {"red": 2, "blue": 3, "green": 1}
T = typing.TypeVar("T")
def counter_pythonic(l: list[T]) -> dict[T, int]:
# um, may be be O(n²) 😅
return {thing: l.count(thing) for thing in set(l)}
def counter_reduce(l: list[T]) -> dict[T, int]:
return functools.reduce(
lambda acc, x: acc | {x: acc.get(x, 0) + 1},
l,
{},
)
def test_it_works_pythonic():
assert counter_pythonic(things) == expected
def test_it_works_reduce():
assert counter_reduce(things) == expected
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment