I have the following highly simplified structure
elements = [{"id": "1", "counts": [1, 2, 3]},
{"id": "2", "counts": [4, 5, 6]}]
I'd like to be able to construct, using glom
, a new dictionary of the form {<id>: <counts[pos]>}
, e.g. for pos = 2
:
{"1": 3, "2": 6}
or alternatively a list/tuple of tuples
[("1",3), ("2", 6)]
Using a dict comprehension
is easy, but the data structure is more complicated and I'd like to dynamically specify what to extract. The previous example would be the simplest thing I'd like to achieve.
After a while I managed to solve it as follows
from glom import glom, T
elements = [{"id": "1", "counts": [1,2,3]},{"id": "2", "counts": [4,5,6]}]
def extract(elements, pos):
extracted = glom(elements, ({"elements": [lambda v: (v["id"], v["counts"][pos])]}, T))
return dict(extracted["elements"])
But this requires a call to dict
. A slight variation that skips a dictionary indirection would be
def extract(elements, pos):
extracted = glom(elements, (([lambda v: {v["id"]: v["counts"][pos]}]), T))
return {k: v for d in extracted for k, v in d.items()}
Now, I could use the merge
function called onto the returned values from the glom
call
def extract(elements, pos):
return merge(glom(elements, (([lambda v: {v["id"]: v["counts"][pos]}]), T)))
I'm rather satisfied with this, but is there a better approach to do this? And with better I mean building a single cleaner spec callable? Ultimately, I'd like to be able to define at runtime in a user friendly way the values of the dictionary, i.e., v["counts"][pos]
.
An improvement towards this idea would be to use a callable to be invoked for the value of the internal dictionary
def counts_position(element, **kwargs):
return element["counts"][kwargs["pos"]]
def extract(elements, func, **kwargs):
return merge(glom(elements, (([lambda v: {v["id"]: func(v, **kwargs)}]), T)))
extract(values, counts_position, pos=2)
With this, what's begin extracted from each element can be controlled externally.