Более элегантный и эффективный способ перебора вложенных слов? - PullRequest
0 голосов
/ 01 октября 2019

Имеется 2 набора параметров:

fb_config = {
  "page_likes" : {
    "page_id": "1111",
                       "metric": "page_fans",
                       "since": "2019-01-01 00:00:00",
                       "until": "2019-01-01 00:00:00",
                       "date_preset" : "yesterday",
                       "period": "day"},

    "page_impressions" : {"page_id": "1111",
                       "metric": "page_impressions",
                       "since": "yesterday",
                       "until": "yesterday",
                       "date_preset" : "yesterday",
                       "period": "day"},

    "page_engaged_users" : {"page_id": "1111",
                       "metric": "page_engaged_users",
                       "since": "today",
                       "until": "today",
                       "date_preset" : "yesterday",
                       "period": "day"}}

и

ga_config =

{

'view_id_123': {'view_id': '123',
                           'start_date': "2019-01-01 00:00:00",
                           'end_date': "2019-01-01 00:00:00",
                           'metrics': [{'expression': 'ga:sessions'}, {'expression':'ga:pageviews'}, {'expression':'ga:users'}, {'expression':'ga:bounces'},
                          {'expression':'ga:avgSessionDuration'}],
                           'dimensions': [{'name': 'ga:year'}, {'name': 'ga:userType'}, {'name': 'ga:sessionCount'}, {'name': 'ga:browser'},
                                          {'name': 'ga:source'}]},

'view_id_456': {'view_id': '456',
                           'start_date': "today",
                           'end_date': "today",
                           'metrics': [{'expression': 'ga:bounces'}, {'expression':'ga:users'}],
                           'dimensions': [{'name': 'ga:mobileDeviceModel'}, {'name': 'ga:dataSource'}]},

'view_id_789': {'view_id': '789',
                           'start_date': "yesterday",
                           'end_date': "yesterday",
                           'metrics': [{'expression': 'ga:bounces'}, {'expression':'ga:users'}],
                           'dimensions': [{'name': 'ga:mobileDeviceModel'}, {'name': 'ga:dataSource'}]}

}

В коде я не могу сохранить параметры и хочу извлечь их из файла json. После загрузки файла все даты должны быть преобразованы из формата str в формат datetime.

Этот процесс осуществляется через несколько циклов:

for values in params.values():
    if 'since' in values:
        if values['since'] == 'today':
            values['since'] = datetime.now()
        elif values['since'] == 'yesterday':
            values['since'] = datetime.now() - timedelta(1)
        else: 
            values['since'] = dt.datetime.strptime(values['since'], '%Y-%m-%d %H:%M:%S')

for values in params.values():
    if 'until' in y:
        if values['until'] == 'today':
            values['until'] = datetime.now()
        elif values['until'] == 'yesterday':
            values['until'] = datetime.now() - timedelta(1)
        else:
            values['until'] = dt.datetime.strptime(y['until'], '%Y-%m-%d %H:%M:%S')

for values in params.values():
    if 'start_date' in values:
        if values['start_date'] == 'today':
            values['start_date'] = datetime.now()
        elif values['start_date'] == 'yesterday':
            values['start_date'] = datetime.now() - timedelta(1)
        else:
            values['start_date'] = dt.datetime.strptime(values['start_date'], '%Y-%m-%d %H:%M:%S')

for values in params.values():
    if 'end_date' in values:
        if values['end_date'] == 'today':
            values['end_date'] = datetime.now()
        elif values['end_date'] == 'yesterday':
            values['end_date'] = datetime.now() - timedelta(1)
        else:
            values['end_date'] = dt.datetime.strptime(values['end_date'], '%Y-%m-%d %H:%M:%S')

Но код действительно ужасен и DRY нарушается. Есть ли лучшие способы перебора вложенных диков и изменения значений определенных ключей?

Ответы [ 4 ]

1 голос
/ 01 октября 2019

Рассмотрим вложенное понимание словаря и функцию отображения разметки для преобразования времени:

def time_conversion(arg):
    switcher = {
        'today': datetime.now(),
        'yesterday': datetime.now() - timedelta(1)
    }

    output = (datetime.strptime(arg, '%Y-%m-%d %H:%M:%S') 
                  if arg not in switcher.keys() else switcher.get(arg))
    return output


new_params = {outer_k:{inner_k: time_conversion(inner_v) 
                          if inner_k in ('since', 'until', 'date_preset') else inner_v 
                       for inner_k, inner_v in outer_v.items()} 
              for outer_k, outer_v in params.items()}
1 голос
/ 01 октября 2019

Я не являюсь разработчиком Python, но я вижу, что вы циклически повторяете 4 раза для одних и тех же данных, когда вы должны сделать это только один раз:

def formatDate(value, default):
    if value == 'today':
        date = datetime.now()
    elif value == 'yesterday':
        date = datetime.now() - timedelta(1)
    else:
        date = default

    return date

def your_function():

    for values in params.values():
        if 'since' in values:
            values['since'] = formatDate(values['since'], dt.datetime.strptime(values['since'], '%Y-%m-%d %H:%M:%S'))

        if 'until' in values:
            values['until'] = formatDate(values['until'], dt.datetime.strptime(y['until'], '%Y-%m-%d %H:%M:%S'))

        if 'start_date' in values:
            values['start_date'] = formatDate(values['start_date'], dt.datetime.strptime(values['start_date'], '%Y-%m-%d %H:%M:%S'))

        if 'end_date' in values:
            values['end_date'] = formatDate(values['end_date'], dt.datetime.strptime(values['end_date'], '%Y-%m-%d %H:%M:%S'))

Код не проверен, но я бы извлекобщая логика для функции и имеет только один цикл foreach.

1 голос
/ 01 октября 2019

Вместо того, чтобы перебирать вложенный dict после загрузки json, вам нужно использовать метод object_hook json.loads () для десериализации дат при импорте (я предполагаю, что вы используете встроенную библиотеку json для анализа json).

На этот вопрос уже отвечали, пожалуйста, взгляните на эту ветку: Как преобразовать объект даты и времени Python с помощью JSON.loads?

1 голос
/ 01 октября 2019

Это немного компактнее:

for values in params.values():
    for k in ('since','until','start_date','end_date'):
        if k in values:
            if values[k] == 'today':
                values[k] = datetime.now()
            elif values[k] == 'yesterday':
                values[k] = datetime.now() - timedelta(1)
            else: 
                values[k] = dt.datetime.strptime(values[k], '%Y-%m-%d %H:%M:%S')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...