Strukturpräsentving verschachtelte Karte in Python
Posted: 19 May 2025, 08:34
Ich schreibe eine Python -Funktion, die von MAP inspiriert ist, die eine Funktion f: Callable [[A], b] und eine willkürlich verschachtelte Struktur von iTerablen (z. B. Listen von Tupeln von Listen von ... von Objekten vom Typ A ) und zurück. Im Idealfall würde es das Diktat [jeder, ein] auch und "homogen" namentuple s unterstützen, indem F nur auf die Werte angewendet und die Tasten unberührt bleiben (nicht s 'Felder sollten alle einen Typ A haben, damit dies funktioniert).
Zum Beispiel:
Glaubst du, es gibt eine "elegantere" Möglichkeit, dies zu erreichen?
Code: Select all
NamedTuple
Zum Beispiel:
Code: Select all
>>> f = lambda x: x * 2
>>> input = [([1, 2], [3, 4]), {"foo": 5, "bar": 6}]
>>> nested_map(f, input)
[([2, 4], [6, 8]), {"foo": 10, "bar": 12}]
< /code>
Idealerweise wäre es Typ-Hinweis-freundlich in dem Sinne, dass es einem statischen Checker mitteilen würde, dass das Ausgabeobjekt genau die gleiche Struktur wie die Eingabe hat. Obwohl dies wahrscheinlich viel schwieriger zu erreichen ist. und < /li>
Es funktioniert bei statischer Typ -Überprüfung nicht gut. < /li>
< /ul>
import inspect
from collections.abc import Iterable
from typing import Any, Callable, Generator, NamedTuple, cast
type MappableIterable[A] = list[A] | tuple[A] | dict[Any, A] | Generator[A]
type NestedIterable[A] = A | MappableIterable["NestedIterable[A]"]
def nested_map[A, B](
f: Callable[[A], B], nested_structure: NestedIterable[A]
) -> NestedIterable[B]:
"""
Takes a nested iterable structure and applies f to all of its nodes,
returning them in the same structure.
"""
structure = type(nested_structure)
match nested_structure:
case dict():
return {
k: nested_map(f, v)
for k, v in nested_structure.items()
}
# NamedTuple
case _ if hasattr(structure, "_fields") and isinstance(
getattr(structure, "_fields"), tuple
):
d = {
k: nested_map(f, v) for
k, v in cast(NamedTuple, nested_structure)._asdict().items()
}
return cast(NestedIterable[B], structure(**d))
case _ if inspect.isgenerator(nested_structure):
return ( nested_map(f, s) for s in nested_structure )
# Have to check str first since it is an Iterable
case str():
return f(nested_structure)
case Iterable():
structure = cast(type[list], structure)
return structure(map(lambda s: nested_map(f, s), nested_structure))
case _:
return f(nested_structure)