I have a data object like this:
data = {
'props': {
'items': [
{'name': 'a', 'content': 'plain'},
{'name': 'b', 'content': {'id': 'x'}},
{'name': 'c', 'content': {'id': 'y'}},
]
}
}
Using glom
, I want to get x
which is the value of id
for the item with name
equal to b
.
So far, I have this:
from glom import glom
from glom import SKIP
glom(data, ('props.items', [lambda i: i if i['name']=='b' else SKIP]))
Which returns:
[{'name': 'b', 'content': {'id': 'x'}}]
I can't figure out what spec (in glom
parlance) to use to extract the only element in the returned list and then the value of id
.
I could call glom twice:
glom(glom(data, ('props.items', [lambda i: i if i['name']=='b' else SKIP]))[0], 'content.id')
But I figured there should be a way of doing it in one call. Any ideas on how to achieve this?
You were very close! The nice thing about glom chaining (which you're doing with that tuple there), is that you basically never need to call glom twice. You can just chain straight through:
>>> glom(data, ('props.items', [lambda i: i if i['name']=='b' else SKIP], '0.content.id'))
'x'
All I did was add a third element '0.content.id'
, which gets the first item, then the content key, then the id key.
For a slightly more glom-oriented way, you can rewrite that lambda to the following:
>>> glom(data, ('props.items', [Check('name', equal_to='b', default=SKIP)], '0.content.id'))
'x'
It does the same thing and is actually slightly longer, but might read a little better. Combine this with another Check for validation, and you can even prevent the final lookup step if no object with the name is found:
>>> glom(data, ('props.items', [Check('name', equal_to='z', default=SKIP)], Check(default=STOP), '0.content.id'))
[]
Don't forget to import Check
and STOP
if you go that route. Also, if the spec is getting long, you can give it a nice descriptive variable name :) Thanks for the great question!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With