Как извлечь значение данного ключа на основе значения другого ключа из списка вложенных (не всегда существующих) словарей [Python] - PullRequest
0 голосов
/ 19 апреля 2020

У меня есть список словарей с именем api_data, где каждый словарь имеет такую ​​структуру:

{

'location': 
    {
    'indoor': 0, 
    'exact_location': 0, 
    'latitude': '45.502', 
    'altitude': '133.9', 
    'id': 12780, 
    'country': 'IT', 
    'longitude': '9.146'
    },

'sampling_rate': None, 
'id': 91976363, 
'sensordatavalues': 
    [   
        {
        'value_type': 'P1', 
        'value': '8.85', 
        'id': 197572463
        }, 


        {
        'value_type': 'P2', 
        'value': '3.95', 
        'id': 197572466
        }

        {
        'value_type': 'temperature', 
        'value': '20.80', 
        'id': 197572625
        }, 

        {
        'value_type': 'humidity', 
        'value': '97.70', 
        'id': 197572626
        }
    ], 

'sensor': 
    {
    'id': 24645, 
    'sensor_type': 
        {
        'name': 'DHT22', 
        'id': 9, 
        'manufacturer': 
        'various'
        }, 

    'pin': '7'
    }, 

'timestamp': '2020-04-18 18:37:50'

},

Эта структура не полная для каждого словаря, то есть иногда словарь , элемент списка или ключ отсутствует.

Я хочу извлечь значение ключа, когда значение ключа того же словаря равно некоторому значению.
Например, для словаря sensordatavalues, Я хочу, чтобы значение ключа 'value', когда 'value_type' равно 'P1'.

Я разработал этот код, работающий с циклами for и if, но держу пари, что он сильно неэффективен. Как я могу сделать это быстрее и эффективнее?

Обратите внимание, что sensordatavalues всегда существует

for sensor in api_data:

    sensordatavalues = sensor['sensordatavalues']
    # L_sdv = len(sensordatavalues)

    for physical_quantity_recorded in sensordatavalues:

        if physical_quantity_recorded['value_type'] == 'P1':

            PM10_value = physical_quantity_recorded['value']               

Ответы [ 4 ]

1 голос
/ 21 апреля 2020

это альтернатива: jmespath - позволяет искать и фильтровать вложенный dict / json:

сводка jmespath ... для доступа к ключу используйте * Нотация 1005 *, если значения ur находятся в списке, доступ к нему осуществляется через нотацию []

Примечание: dict заключен в переменную data

import jmespath
#sensordatavalues is a key, so we can access it directly
#the values of sensordatavalues are wrapped in a list
#to access it we pass the bracket(```[]```)
#we are interested in the dict where value_type is P1
#in jmespath, we identify that using the ? mark to precede the filter object
#pass the filter
#and finally access the key we are interested in ... value

expression = jmespath.compile('sensordatavalues[?value_type==`P1`].value')
expression.search(data)
['8.85']
1 голос
/ 19 апреля 2020

Используйте метод dictionary.get(), если ключ не существует, он вернет значение по умолчанию

for physical_quantity_recorded in api_data['sensordatavalues']:
    if physical_quantity_recorded.get('value_type', 'default_value') == 'P1':
        PM10_value = physical_quantity_recorded.get('value', 'default_value')
1 голос
/ 19 апреля 2020
  1. Если вы уверены, что значение 'P1' является уникальным для ключа, который вы ищете, вы можете использовать оператор 'in' с dict.values ​​()
  2. Должно быть нормально пропустить это назначение: sensordatavalues = sensor['sensordatavalues']
for sensor in api_data:

    for physical_quantity_recorded in sensor['sensordatavalues']:

        if 'P1' in physical_quantity_recorded.values():

            PM10_value = physical_quantity_recorded['value'] 
1 голос
/ 19 апреля 2020

Вам нужен только один for l oop:

for x in api_data["sensordatavalues"]:
    if x["value_type"] == "P1":
        print(x["value"])

Вывод:

8.85
...