Update Dict in List Comprehensions

Asked

Viewed 80 times

-1

I have some dictionaries that I need to fill recursively and for that I would like to use list comprehensions this way

list_dict = [{'a':'b'},{'a':'c'}]

list_dict = [dict.update({'b':dict['a']}) for dict in list_dict]

The goal was to work with datetime where I would add a value to each dictionary.

The problem is that when using Dict.update() it returns None instead of the dictionary value which returns more or less this:

[None,None]

I also tried to use a map() in this way:

list(map(lambda dict: dict.update({'novo_valor':100}),list_dict))

But I got the same return.

I tried some other things like using and inside the list comprehension but without success.

Does anyone have any ideas that might help.

Practical example:

MAX_DAYS_TO_INACTIVE = 15
MAX_DAYS_TO_EXPIRATION = 30
Entrada = {
        'UserName':'user.1',
        'AccessKeyId':'CCCCCCCCCCCCCCCCCCCC',
        'Status':'Inactive',
     'CreateDate':datetime.datetime(2019,9,10,20,12,45,tzinfo=tzutc())
    },
    {
        'UserName':'user.2',
        'AccessKeyId':'BBBBBBBBBBBBBBBBBBBB',
        'Status':'Active',
      'CreateDate':datetime.datetime(2020,4,16,1,26,18,tzinfo=tzutc())
    }
]

Function I created:

def add_date_paramters(complete_access_key_list):
    key_list = list()
    for acess_key in complete_access_key_list:
        acess_key.update(
            {
                'InvalidationDate':acess_key['CreateDate']+datetime.timedelta(days=MAX_DAYS_TO_INACTIVE),
                'ExpirationDate':acess_key['CreateDate']+datetime.timedelta(days=MAX_DAYS_TO_EXPIRATION),
            }
        )
        key_list.append(acess_key)
    return key_list

I hope I have something like this:

saida = [ {
        'UserName':'user.1',
        'AccessKeyId':'CCCCCCCCCCCCCCCCCCCC',
        'Status':'Inactive',
        'CreateDate':datetime.datetime(2019,9,10,20,12,45,tzinfo=tzutc()),
        'InvalidationDate':datetime.datetime(2019, 9, 25, 20, 12, 45, tzinfo=tzutc()),
        'ExpirationDate':datetime.datetime(2019, 10, 10, 20, 12, 45, tzinfo=tzutc())
    },
    {
        'UserName':'user.2',
        'AccessKeyId':'BBBBBBBBBBBBBBBBBBBB',
        'Status':'Active',
        'CreateDate':datetime.datetime(2020,4,16,1,26,18,tzinfo=tzutc()),
        'InvalidationDate':datetime.datetime(2020, 5, 1, 1, 26, 18, tzinfo=tzutc()),
        'ExpirationDate':datetime.datetime(2020, 5, 16, 1, 26, 18, tzinfo=tzutc())
    }, ]
  • 1

    You have at least one practical example with an input and expected output ?

  • sorry I could not answer everything here, completed in question

  • @Lacobus Thanks I managed to solve.

2 answers

1


Basic solution in which the list of dictionaries is updated in-place:

from dateutil.tz import tzutc
from datetime import timedelta, datetime

MAX_DAYS_TO_INACTIVE = 15
MAX_DAYS_TO_EXPIRATION = 30

list_dict = [
    {
        'UserName'   : 'user.1',
        'AccessKeyId': 'CCCCCCCCCCCCCCCCCCCC',
        'Status'     : 'Inactive',
        'CreateDate' : datetime(2019,9,10,20,12,45,tzinfo=tzutc())
    },
    {
        'UserName'   : 'user.2',
        'AccessKeyId': 'BBBBBBBBBBBBBBBBBBBB',
        'Status'     : 'Active',
        'CreateDate' : datetime(2020,4,16,1,26,18,tzinfo=tzutc())
    }
]

for dic in list_dict:
    dic['InvalidationDate'] = dic['CreateDate'] + timedelta(days=MAX_DAYS_TO_INACTIVE)
    dic['ExpirationDate'] = dic['CreateDate'] + timedelta(days=MAX_DAYS_TO_EXPIRATION)

print(list_dict)

Exit:

[
  {
    'UserName': 'user.1',
    'AccessKeyId': 'CCCCCCCCCCCCCCCCCCCC',
    'Status': 'Inactive',
    'CreateDate': datetime.datetime(2019, 9, 10, 20, 12, 45, tzinfo=tzutc()),
    'InvalidationDate': datetime.datetime(2019, 9, 25, 20, 12, 45, tzinfo=tzutc()),
    'ExpirationDate': datetime.datetime(2019, 10, 10, 20, 12, 45, tzinfo=tzutc())
  },
  {
    'UserName': 'user.2',
    'AccessKeyId': 'BBBBBBBBBBBBBBBBBBBB',
    'Status': 'Active',
    'CreateDate': datetime.datetime(2020, 4, 16, 1, 26, 18, tzinfo=tzutc()),
    'InvalidationDate': datetime.datetime(2020, 5, 1, 1, 26, 18, tzinfo=tzutc()),
    'ExpirationDate': datetime.datetime(2020, 5, 16, 1, 26, 18, tzinfo=tzutc())
  }
]

See working on Repl.it

Encapsulating in a function:

def add_date_parameters(lst):
    for dic in lst:
        dic.update({
            'InvalidationDate': dic['CreateDate'] + timedelta(days=MAX_DAYS_TO_INACTIVE),
            'ExpirationDate'  : dic['CreateDate'] + timedelta(days=MAX_DAYS_TO_EXPIRATION)
        })
    return lst
  • Create the unit tests for the two functions and really your form is more performative. 1,000,000 requests the function got the following results. made a stress test with === 1 passed, 1 Warning in 8.28s == vs: ===1 passed, 1 Warning in 15.78s === For few requests it is usually close to 0.50. ?

0

I called a friend and explained the case.

He suggested me use the operated or when the dict.update() return None the expression consider the return as what comes after:

solution:

def add_date_paramters(complete_access_key_list):
    return map( lambda acess_key: acess_key.update(
        {
            'InvalidationDate':acess_key['CreateDate']+datetime.timedelta(days=MAX_DAYS_TO_INACTIVE),
            'ExpirationDate':acess_key['CreateDate']+datetime.timedelta(days=MAX_DAYS_TO_EXPIRATION)
        }
    ) or acess_key ,complete_access_key_list)

My mistake was trying to use and which ended up being fake on the first check and didn’t return anything. Thank you for your attention.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.