Last active
October 24, 2023 22:28
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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