简体   繁体   中英

Get value from list of nested dict in Python based on key

I have a list of dict, need to get the int_value from the sub-dict of values based on the value of the key.

my_list = [{'key': 'previous_id',
  'value': {'int_value': '-4343583665607944462'}},
 {'key': 'event_origin', 'value': {'string_value': 'auto'}},
 {'key': 'screen_id', 'value': {'int_value': '-5880567181845583757'}},
 {'key': 'previous_class', 'value': {'string_value': 'MainActivity'}},
 {'key': 'screen', 'value': {'string_value': 'Gateway'}},
 {'key': 'screen_class', 'value': {'string_value': 'Gateway'}}]

For example, I need to get -4343583665607944462 as a string output for previous_id.

This is what I got so far, which looks over complicated to me, want to know if there is more straightforward way to achieve that.

for d in my_list:
    if list(d.values())[0] == 'previous_id':
        print(list(d.values())[1].values())

Get -4343583665607944462 as a string output for previous_id.

Please also suggest if define a function would make sense.

I'd suggestion checking if the first value is "previous_id" by using the "key" key rather than .values()[0] , and same for getting the value. If you know the keys ahead of time, this is the recommended way of accessing data from a dictionary.

If you want to simplify your code, you could use the next function, which loops over an iterable and returns the first value it finds (that matches the given condition if there is one).

For example:

value = next(d["value"] for d in my_list if d["key"] == "previous_id")

This would return

{'int_value': '-4343583665607944462'}

If you want just "-4343583665607944462" , then you could do:

value = next(list(d["value"].values())[0] for d in my_list if d["key"] == "previous_id")

Note here we use .values()[0] because the keys are not always the same.

Also next raises a StopIteration exception if it reaches the end of the iterable without finding a match so consider wrapping it in a try / except block.

It may be worth while to preprocess your initial list of dicts, something like:

key_to_int = {}
for d in my_list:
    if 'int_value' in d['value']:
        key_to_int[d['key']] = d['value']['int_value']
    else:
        key_to_int[d['key']] = None

You can then simply do:

print(key_to_int['previous_id'])
print(key_to_int['event_origin'])
print(key_to_int['screen_id'])

Which outputs:

-4343583665607944462
None
-5880567181845583757

The above assumes all your dicts follow the same format. In the case where some dicts may be nested deeper than others, some modifications need to be made.

I don't know if you have access to modifying the actual list beforehand, but it would probably make more sense to keep the type of value inside a single dict eg:

my_list = [{
    'key': 'previous_id',
    'value': '-4343583665607944462',
    'type': 'int_value' },...]

This way you could simply call:

for dict in my_list:
    if dict['key']=='previous_id':
        return dict['value']

or a one-liner:

value = [x['values'] for x in my_list if x['key']=='previous_id']

and if you are keen on having the value type

value = {x['type']:x['values'] for x in my_list if x['key']=='previous_id'}

If you would like use the same dictionary and stick with your method, you can use:

for d in my_list:
    if d["key"] == 'previous_id':
        print(list(d["value"].values())[0])

But would recommend you to use a dictionary like this:

my_dict = {"previous_id": '-4343583665607944462', 'event_origin':'auto',  
    'screen_id':-5880567181845583757,  'previous_class': 'MainActivity',
    'screen': 'Gateway',  'screen_class': 'Gateway'}

Then you can use print simply like this:

print(my_dict["previous_id"])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM