2016-12-02 3 views
2

Я работаю над реализацией Python AWS Cognito с помощью boto3. jwt.decode на IdToken дает полезную нагрузку, которая находится в форме словаря, например, так:Объединить только значения списка словарей python в один словарь

{ 
    "sub": "a uuid", 
    "email_verified": True, 
    "iss": "https://cognito-idp....", 
    "phone_number_verified": False, 
    "cognito:username": "19407ea0-a79d-11e6-9ce4-09487ca06884", 
    "given_name": "Aron Filbert", 
    "aud": "my client app", 
    "token_use": "id", 
    "auth_time": 1480547504, 
    "nickname": "Aron Filbert", 
    "phone_number": "+14025555555", 
    "exp": 1480551104, 
    "iat": 1480547504, 
    "email": "[email protected]" 
} 

Так я разработал класс User, потребляющий, что словарь. Отлично работает, пока мне не понадобится снова нажать Cognito и получить новые сведения о пользователе, чтобы убедиться, что ничего не изменилось (скажем, с другого устройства). Мое возвращение полезной нагрузки от get_user() вызова заканчивает тем, как список словарей:

[ 
    { 
     "Name": "sub", 
     "Value": "a uuid" 
    }, 
    { 
     "Name": "email_verified", 
     "Value": "true" 
    },   
    { 
     "Name": "phone_number_verified", 
     "Value": "false" 
    }, 
    { 
     "Name": "phone_number", 
     "Value": "+114025555555" 
    }, 
    { 
     "Name": "given_name", 
     "Value": "Aron Filbert" 
    }, 
    { 
     "Name": "email", 
     "Value": "[email protected]" 
    }   
] 

Так как я мог быть удар, что get_user() Cognito конечной точки много, я искал эффективный способ, чтобы захватить только значения каждого словарь в списке и использовать их для формирования ключей: значения нового словаря. Пример:

{ 
    "sub": "a uuid", # From first list item 
    "email_verified": True, # From next list item   
    ... 
} 

Будучи новым для Python, я изо всех сил стараюсь сделать это элегантно и эффективно.

+1

Сначала вы должны делать это просто и неэффективно, а затем беспокоиться об улучшениях (так вы учитесь). Вы пробовали что-то прямое/грубое? –

+0

Полностью согласен. Причина, по которой я спрашиваю, заключается в том, что я нахожусь в крайнем случае, используя задний конец, с которым я не знаком. Я написал быстрый итератор для выполнения моей задачи и рассмотрел использование 'any()', а также надеялся на более питоновское решение – afilbert

+2

'{k [" Name "]: k [" Value "] для k in list_of_dicts_from_get_user} '? –

ответ

2

Как я отметил в комментарии, большая часть работы может быть сделано Dict понимания:

lst = get_user() # or something similar, lst is a list of dicts 
parsed_res = {k["Name"]:k["Value"] for k in lst} 

Это только отличается от ожидаемого выхода в том, что она содержит 'true' и 'false' в то время как вы хотите Bools в ваш конечный результат. Ну, самое простое решение, чтобы определить функцию, которая делает это преобразование для вас:

def boolify(inp): 
    if inp=='true': 
     return True 
    elif inp=='false': 
     return False 
    else: 
     return inp 

parsed_res = {k["Name"]:boolify(k["Value"]) for k in lst} 

То же самое может быть сделано в самом понимании, но это не было бы более ясным, ни эффективным. Таким образом, вы можете делать дополнительные манипуляции в своих ключах, если позже поймете, что перед хранением есть другие вещи, которые вы хотите сделать с вашей полезной нагрузкой.

1

Понимание словаря, как сказал Андрас выше, представляет собой простой, один-лайнер Pythonic для вашего случая. Некоторые принципы стиля (such as Google's), однако, рекомендовать против них, если они представляют сложную логику или занять более двух или трех линий:

хорошо использовать для простых случаев. Каждая часть должна соответствовать одной строке: отображение выражения, для предложения, выражение фильтра. Множественные для предложения или выражения фильтра не разрешены. Вместо этого используйте петли вместо , когда ситуация усложняется.

Да:

result = [] 
for x in range(10): 
    for y in range(5): 
     if x * y > 10: 
      result.append((x, y)) 

for x in xrange(5): 
    for y in xrange(5): 
     if x != y: 
      for z in xrange(5): 
       if y != z: 
        yield (x, y, z) 

return ((x, complicated_transform(x)) 
     for x in long_generator_function(parameter) 
     if x is not None) 

squares = [x * x for x in range(10)] 

eat(jelly_bean for jelly_bean in jelly_beans 
    if jelly_bean.color == 'black') 

№:

result = [(x, y) for x in range(10) for y in range(5) if x * y > 10] 

return ((x, y, z) 
     for x in xrange(5) 
     for y in xrange(5) 
     if x != y 
     for z in xrange(5) 
     if y != z) 

словарь понимание не вполне уместно в вашем случае, но для полноты картины, это общий метод выполняя операции с парой петель, если вы решите сделать что-нибудь более интересное:

for <dict> in <list>: 
    for <key>, <value> in <dict>: 
     # Perform any applicable operations. 
     <new_dict>[<key>] = <value> 

, который выходит ...

user = get_user() 
user_info = {} 

for info in user: 
    for name, value in info: 
     n, v = info[name], info[value] 
     if v.lowercase() == 'true': 
      v = True 
     else if v.lowercase() == 'false': 
      v = False 
     user_info[n] = v 
Смежные вопросы