Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: deep appending to dictionary? - in a single expression

Tags:

python

How do I, in a single expression, get a dictionary where one key-value pair has been added to a sub-dictionary in some input dictionary? The input dictionary should be left unchanged. It can be assumed the sub-dictionary does exist and that the new key-value pair is not already in the sub-dictionary.

Update 2 (see below for definition of "SOsurvivalConditions", etc.):

The most concise way is:

(SOsurvivalConditions['firstCondition'].setdefault('synonym', 'A modern form of RTFM is: Google It.'), SOsurvivalConditions)[-1]

Update 1 :

This meets the given requirements and does not have the side-effect of modifying the input dictionary:

dict((k,dict(v, synonym='A modern form of RTFM is: Google It.') if k == "firstCondition" else v) for k,v in SOsurvivalConditions.iteritems())

However the more concise (but statement only) way can be adapted with a helper function, e.g.:

import copy
def dictDeepAdd(inputDict, dictKey, newKey, newValue):
    """
      Adds new key-value pair to a sub-dictionary and
      returns a new version of inputDict.

      dictKey is the key in inputDict for which a new
      key-value pair is added.

      Side-effect: none (does not change inputDict).
    """
    toReturn = copy.deepcopy(inputDict)
    toReturn[dictKey][newKey] = newValue
    return toReturn

dictDeepAdd(
                 SOsurvivalConditions,
                 'firstCondition',
                 'synonym',
                 'A modern form of RTFM is: Google It.'
           )

The Example:

goodStyle = \
{
    'answer': 'RTFM responses are not acceptable on Stack Overflow - Joel Spolsky has repeatedly said so in the Stack Overflow podcasts.',
    'RTFM'  : 'RTFM is, in the less offensive version, an abbreviation for Read The Fine Manual.',
}

SOsurvivalConditions = \
{
    'moodImperative' : 'be happy',
    'firstCondition' : goodStyle,
}

'firstCondition' in SOsurvivalConditions now has two key-value pairs. A new key-value pair, ('synonym', 'A modern form of RTFM is: Google It.'), needs to be appended and the result should be available in a single expression.

This works (one line, but broken into several here):

{
    'moodImperative': SOsurvivalConditions['moodImperative'],
    'firstCondition' :
        dict(
               SOsurvivalConditions['firstCondition'],
               synonym = 'A modern form of RTFM is: Google It.'
            )
}

and returns:

{'moodImperative': 'be happy', 
 'firstCondition': 
        {'answer': 'RTFM responses are not acceptable on Stack Overflow - Joel Spolsky has repeatedly said so in the Stack Overflow podcasts.', 
         'RTFM': 'RTFM is, in the less offensive version, an abbreviation for Read The Fine Manual.', 
         'synonym': 'A modern form of RTFM is: Google It.'
        }
 }

However there is a lot of redundancy in this expression - all keys are repeated. And 'firstCondition' appears two times. Is there a more elegant way?

(The names and the content of the datastructures here are made up, but represent a real problem I encountered today. Python version: 2.6.2.).

like image 672
Peter Mortensen Avatar asked Jul 05 '09 19:07

Peter Mortensen


1 Answers

SOsurvivalConditions['firstCondition']['synonym'] = 'A modern form of RTM is: Google It.'
like image 78
Evan Fosmark Avatar answered Oct 12 '22 23:10

Evan Fosmark