@chrispsow

Есть ли в Python возможность нахождения пути в словаре до определенного значения?

Работаю с API
Есть два словаря
Первый:
my = {
			'id1': {
				'p1': 'Sloane Stephens',
				'p2': 'Polona Hercog',
				'p1_odds': 1.2,
				'p2_odds': 3.8,
				'isfound': False
			},
			'id2': {
				'p1': 'Belinda Bencic',
				'p2': 'Donna Vekic',
				'p1_odds': 1.8,
				'p2_odds': 2.1,
				'isfound': False
			}
		}


И второй который приходит по апи:
{  
   'sportId':123,
   'last':216699817,
   'league':[
   		{  
         'id':3742,
         'name':'WTA French Open - R3',
         'events':[               
            {  
               'id':9999999999999,
               'starts':'2019-05-31T11:30:00Z',
               'home':'Sloane Stephens',
               'away':'Polona Hercog',
               'rotNum':'8705',
               'liveStatus':0,
               'status':'I',
               'parlayRestriction':2,
               'parentId':994897148,
               'altTeaser':False,
               'resultingUnit':'Sets'
            },
            {  
               'id':994906276,
               'starts':'2019-05-31T11:30:00Z',
               'home':'Veronika Kudermetova (+1.5 Sets)',
               'away':'Kaia Kanepi (-1.5 Sets)',
               'rotNum':'8705',
               'liveStatus':0,
               'status':'I',
               'parlayRestriction':2,
               'parentId':994897148,
               'altTeaser':False,
               'resultingUnit':'Sets'
            }
         ]
      	},
      	{  
         'id':3735,
         'name':'WTA French Open - Doubles',
         'events':[  
            {  
               'id':994977085,
               'starts':'2019-05-31T11:30:00Z',
               'home':'L Hradecka / A Klepac',
               'away':'S Kenin / A Petkovic',
               'rotNum':'15571',
               'liveStatus':0,
               'status':'O',
               'parlayRestriction':2,
               'altTeaser':False,
               'resultingUnit':'Regular'
            },
            {  
               'id':995164497,
               'starts':'2019-05-31T12:45:00Z',
               'home':'M Puig / S Rogers',
               'away':'S Hsieh / B Strycova',
               'rotNum':'15575',
               'liveStatus':0,
               'status':'I',
               'parlayRestriction':2,
               'altTeaser':False,
               'resultingUnit':'Regular'
            }
         ]
      	}
    ]
}


Мне нужно проверять есть ли во втором словаре(отчете апи) значение в home, которое есть в первом словаре. В данном случае это будет "Sloane Stephens"
Если оно есть, то нужно присвоить его id в данном случае это "9999999999999"

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

Можеть быть можно лучше организовать мой первый словарь?

Про путь я имел ввиду, что может быть если бы мы нашли последовательный список из ключей то смогли бы по нему достать значение из 'id'
тут это будет ['league'][0]['events']['id']
Зная, что в ['league'][0]['events']['home'] у нас нужное значение
  • Вопрос задан
  • 186 просмотров
Пригласить эксперта
Ответы на вопрос 2
Вот пример кода который, поможем вам найти объект в неопределенной вложенности.
Но придется допилить под свои нужды
from pprint import pprint

TRUE_COUNT = 2


def yes(obj: dict, values: dict):
    obj_values = {v for v in obj.values() if isinstance(v, (str, int, float, tuple, bool))}
    return len(obj_values.intersection(values.values())) >= TRUE_COUNT


def find(key, keys, obj, accept_values):
    find_obj = None
    if isinstance(obj, dict):
        if yes(obj, accept_values):
            find_obj = obj
        else:
            for key, value in obj.items():
                find_obj = find(key, keys, value, accept_values)
                if find_obj:
                    break

    elif isinstance(obj, list):
        for key, value in enumerate(obj):
            find_obj = find(key, keys, value, accept_values)
            if find_obj:
                break

    if find_obj:
        keys.append(key)
        pprint(list(reversed(keys)))
        return find_obj


for accept in my.values():
    pprint(find('', [], rr, accept))
Ответ написан
Комментировать
half-life
@half-life
from dataclasses import dataclass
from itertools import chain
from itertools import filterfalse
from itertools import product
from typing import List


@dataclass
class Obj:
    p1: str
    p2: str
    p1_odds: float
    p2_odds: float
    is_found: bool = False
    external_id: int = -1


API_RESPONSE = {
    'sportId': 123,
    'last': 216699817,
    'league': [
        {
            'id': 3742,
            'name': 'WTA French Open - R3',
            'events': [
                {
                    'id': 9999999999999,
                    'starts': '2019-05-31T11:30:00Z',
                    'home': 'Sloane Stephens',
                    'away': 'Polona Hercog',
                    'rotNum': '8705',
                    'liveStatus': 0,
                    'status': 'I',
                    'parlayRestriction': 2,
                    'parentId': 994897148,
                    'altTeaser': False,
                    'resultingUnit': 'Sets'
                },
                {
                    'id': 994906276,
                    'starts': '2019-05-31T11:30:00Z',
                    'home': 'Veronika Kudermetova (+1.5 Sets)',
                    'away': 'Kaia Kanepi (-1.5 Sets)',
                    'rotNum': '8705',
                    'liveStatus': 0,
                    'status': 'I',
                    'parlayRestriction': 2,
                    'parentId': 994897148,
                    'altTeaser': False,
                    'resultingUnit': 'Sets'
                }
            ]
        },
        {
            'id': 3735,
            'name': 'WTA French Open - Doubles',
            'events': [
                {
                    'id': 994977085,
                    'starts': '2019-05-31T11:30:00Z',
                    'home': 'L Hradecka / A Klepac',
                    'away': 'S Kenin / A Petkovic',
                    'rotNum': '15571',
                    'liveStatus': 0,
                    'status': 'O',
                    'parlayRestriction': 2,
                    'altTeaser': False,
                    'resultingUnit': 'Regular'
                },
                {
                    'id': 995164497,
                    'starts': '2019-05-31T12:45:00Z',
                    'home': 'M Puig / S Rogers',
                    'away': 'S Hsieh / B Strycova',
                    'rotNum': '15575',
                    'liveStatus': 0,
                    'status': 'I',
                    'parlayRestriction': 2,
                    'altTeaser': False,
                    'resultingUnit': 'Regular'
                }
            ]
        }
    ]
}


def find_matching(container: List[Obj], api_response: dict) -> List[Obj]:
    events = (
        tuple(
            (e.get('id', 0), e.get('home', '')) for e in
            chain.from_iterable(
                filter(None, (event.get('events', []) for event
                              in api_response.get('league', [])))
            )
        )
    )
    result = []
    filtered = filterfalse(lambda x: x[0].p1 != x[1][1], product(container, events))
    for obj, item in filtered:
        obj.external_id = item[0]
        obj.is_found = True
        result.append(obj)
    return result


if __name__ == '__main__':
    data = [
        Obj(
            p1='Sloane Stephens',
            p2='Polona Hercog',
            p1_odds=1.2,
            p2_odds=3.8,
        ),
        Obj(
            p1='Belinda Bencic',
            p2='Donna Vekic',
            p1_odds=1.8,
            p2_odds=2.1,
        ),
    ]
    result = find_matching(data, API_RESPONSE)
    print(result)

# [Obj(p1='Sloane Stephens', p2='Polona Hercog', p1_odds=1.2, p2_odds=3.8, is_found=True, external_id=9999999999999)]
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы