Xdict
This type can be seen as a kind of list of couples of (key, value), with a few specificities. Due to its nature of dictionary, navigating between a set of keys and a list of values, only the applicative aspect is kept here (map
, filter
, …), leaving monadic behaviors (flat_map
) on the side. However, conversion to and from Xlist are available to let the user creates is own semantic when flattening behavior is required.
from xfp import Xdict
xdict = Xdict({"a": 1, "b": 20})
xdict_filtered = xdict.filter_values(lambda x: x < 10)
xdict.foreach_keys(print) # prints a, b
xdict_filtered.foreach_keys(print) # prints a
Integration with Xlist
Using items()
and from_list()
it is possible to convert an Xdict to an Xlist and back. from_list
automatically handles the keys to ensure unicity, while items()
creates an Xlist of (key, value) couples in an arbitrary order.
This enables to lift the Xlist functionalities to the Xdict, while letting the user defines its own edge-cases matching its needs. Here is an example of multiple ways to flatten Xdicts:
- First case: We don’t care about key reconciliation
from xfp import Xdict from xpf.functions import tupled2, F1 input = Xdict({"a": 1, "b": 2}) def flat_map[T, U, Y, X](xdict: Xdict[Y, X], f: F1[[Y, X], Xdict[T, U]]) -> Xdict[T, U]: return Xdict.from_list(xdict.items().flat_map(tupled2(f))) result = flat_map(input, lambda y, x: Xdict({f"{y}{y}": x * x, f"{y}{y}{y}": x * x * x})) assert result = Xdict({"aa": 1, "aaa": 1, "bb": 4, "bbb": 8})
- Second case: The same key may be found accross multiple reduction, we need a custom reconciliation
from xfp import Xdict from xpf.functions import tupled2, F1 input = Xdict({"a": 1, "b": 2}) def flat_map[T, U, Y, X](xdict: Xdict[Y, X], f: F1[[Y, X], Xdict[T, U]]) -> Xdict[T, U]: fmapped = xdict.items().flat_map(tupled2(f)) return Xdict.from_list( Xlist(set(iter(fmapped.map(tupled2(lambda y, _: y))))) # we get a list of distinct keys .map(lambda x: fmapped.filter(tupled2(lambda y, _: x == y))) # we split our flat_mapped (key, value) list by keys .map(lambda l: l.max(tupled2(lambda _, x: x))) # we only keep the maximum value for each sublist ) result = flat_map(input, lambda y, x: Xdict({f"{y}{y}": x * x, f"cube": x * x * x})) assert result = Xdict({"aa": 1, "cube": 8, "bb": 4})
Extended API
Xdict revolves around its (key, value) structure to add indexed search and update methods :
updated
returns a new Xdict, with an value upserted.removed
returns a new Xdict, with a couple (key, value) deleted when the key is found.
from xfp import Xdict
assert Xdict({"a": 1}).updated("b", 2) == Xdict({"a": 1, "b": 2})
assert Xdict({"a": 1, "b": 2}).removed("b") == Xdict({"a": 1})