Search code examples
pythondictionary-comprehension

Python dict comprehension - access dict during creation


I have a code like this:

dictionary = {}

for x in dict_of_x:
  if x['duration_to_cancel'] == None or x['duration_to_cancel'] > 5:
    key = x['key']
    value = x['value']

    if key not in dictionary or value > dictionary[key]:
      dictionary[key] = value

I want to make this code a dict comprehension:

dictionary = {x['key'] : x['value'] for x in dict_of_x \
            if ( True if x['duration_to_cancel'] == None else x['duration_to_cancel'] > 5)}

How can I include the second if statement in the 1st code box, to the dict comprehension?


Solution

  • Since all you are doing is a max you can use "max comprehension":

    dict_of_x = (
        {'key':0,'value':0,'duration_to_cancel':10},
        {'key':0,'value':1,'duration_to_cancel':15},
        {'key':0,'value':2,'duration_to_cancel':1},
        {'key':1,'value':3,'duration_to_cancel':2},
        {'key':2,'value':4,'duration_to_cancel':None}
    )
    
    def yours():
        dictionary = {}
        for x in dict_of_x:
          if x['duration_to_cancel'] == None or x['duration_to_cancel'] > 5:
            key = x['key']
            value = x['value']
            if key not in dictionary or value > dictionary[key]:
              dictionary[key] = value
        return dictionary
    print yours()
    
    {0: 1, 2: 4}
    
    def mine(): 
        dictionary = {key : max(x['value'] for x in dict_of_x if x['key'] == key) \
            for key in set(x['key'] for x in dict_of_x if x['duration_to_cancel'] == None or x['duration_to_cancel'] > 5)}
        return dictionary
    print mine()
    
    {0: 1, 2: 4}
    

    Note however that list/dict/set/max comprehension just for the sake of it is not necessarily a good thing for readability. Also in you implementation you go through your dict only once, while my code will loop several times through it, which also comes with reduced speed:

    %timeit yours()
    1000000 loops, best of 3: 855 ns per loop
    
    
    %timeit mine() 
    100000 loops, best of 3: 2.32 µs per loop