Yeti
Yeti

Reputation: 877

Defined dict entries Python

Any ideas how to make something like the following?

Let there be:

a = {'p': 1, 'r': 2}
b = {'p': 1, 'r': 3}

This is a simplified entry, however imagine that there are more common key-value pairs, so the goal is to make the definition smaller and more readable. Is there any way to alias it such that I can write e.g.:

m = ('p': 1)  # note this does not work
a = {m, 'r': 2}
b = {m, 'r': 3}

Here's an obfuscated version of my issue:

what = {
        sr: [{'los_angels': mg, 'sg': sg, 'ua': boston, 'new_york': seattle},
                    {'los_angels': mg, 'sg': sg, 'new_york': seattle},
                    {'los_angels': mg, 'ua': boston, 'new_york': seattle},
                    {'los_angels': mg, 'new_york': seattle},
                    {'los_angels': mg, 'ua': boston, 'new_york': seattle, 'apple': 'IS'},
                    {'los_angels': mg, 'new_york': seattle, 'apple': 'IS'}],
        as: [{'los_angels': mg, 'ua': boston, 'new_york': seattle}, {'los_angels': mg, 'new_york': seattle},
                {'los_angels': mg, 'ua': boston, 'new_york': seattle, 'apple': 'IS'},
                {'los_angels': mg, 'new_york': seattle, 'apple': 'IS'}],
        dd: [{'los_angels': 'orange', 'new_york': seattle},
                    {'los_angels': 'orange', 'new_york': seattle, 'ua': boston},
                    {'los_angels': 'orange', 'new_york': seattle, 'apple': 'IS'},
                    {'los_angels': 'orange', 'new_york': seattle, 'ua': boston, 'apple': 'IS'}],
        a: [{}, {'ua': boston}, {'new_york': seattle}, {'new_york': seattle, 'ua': boston}],
        b: [{}, {'ua': boston}, {'new_york': seattle}, {'new_york': seattle, 'ua': boston}],
        c: [{}, {'ua': boston}, {'new_york': seattle}, {'new_york': seattle, 'ua': boston}],
        d: [{}, {'ua': boston}, {'new_york': seattle}, {'new_york': seattle, 'ua': boston}],
        e: [{}, {'ua': boston}, {'new_york': seattle}, {'new_york': seattle, 'ua': boston}],
        f: [{}, {'ua': boston}, {'new_york': seattle}, {'new_york': seattle, 'ua': boston}],
        g: [{}],
        h: [{}],
        i: [{}, {'los_angels': mg}],
    }

So I'm looking for some way to make the 'los_angels': 'orange' part, 'ua':boston smaller :)

Upvotes: 0

Views: 101

Answers (2)

Martijn Pieters
Martijn Pieters

Reputation: 1122002

You cannot use a predefined key-value pair like that, no, but there are other options:

  • You could define a base dictionary, then update a and b with it:

    m = {'p': 1}
    a = {'r': 2}
    a.update(m)
    b = {'r': 3}
    a.update(m)
    
  • You could use the dict() function to combine two dictionaries into one new one, or to add additional keys as keyword arguments:

    m = {'p': 1}
    a = dict(m, r=2)
    b = dict(m, r=3)
    

    This requires the other keys (like r) to be valid Python identifiers. You could use the ** syntax to work around that limitation:

    m = {'p': 1}
    a = dict(m, **{'r': 2})
    b = dict(m, **{'r': 3})
    

    Now r can be any string again.

  • You could define the key and value as separate variables, and use those:

    m_key, m_value = 'p', 1
    a = {m_key: m_value, 'r': 2}
    b = {m_key: m_value, 'r': 3}
    

Applying the second option to your obfuscated sample:

la_orange = {'los_angels': 'orange'}

what = {
        sr: [{'los_angels': mg, 'sg': sg, 'ua': boston, 'new_york': seattle},
                    {'los_angels': mg, 'sg': sg, 'new_york': seattle},
                    {'los_angels': mg, 'ua': boston, 'new_york': seattle},
                    {'los_angels': mg, 'new_york': seattle},
                    {'los_angels': mg, 'ua': boston, 'new_york': seattle, 'apple': 'IS'},
                    {'los_angels': mg, 'new_york': seattle, 'apple': 'IS'}],
        as: [{'los_angels': mg, 'ua': boston, 'new_york': seattle}, {'los_angels': mg, 'new_york': seattle},
                {'los_angels': mg, 'ua': boston, 'new_york': seattle, 'apple': 'IS'},
                {'los_angels': mg, 'new_york': seattle, 'apple': 'IS'}],
        dd: [dict(la_orange, new_york=seattle),
                    dict(la_orange, new_york=seattle, ua=boston),
                    dict(la_orange, new_york=seattle, apple='IS'),
                    dict(la_orange, new_york=seattle, ua=boston, apple='IS')],
        a: [{}, {'ua': boston}, {'new_york': seattle}, {'new_york': seattle, 'ua': boston}],
        b: [{}, {'ua': boston}, {'new_york': seattle}, {'new_york': seattle, 'ua': boston}],
        c: [{}, {'ua': boston}, {'new_york': seattle}, {'new_york': seattle, 'ua': boston}],
        d: [{}, {'ua': boston}, {'new_york': seattle}, {'new_york': seattle, 'ua': boston}],
        e: [{}, {'ua': boston}, {'new_york': seattle}, {'new_york': seattle, 'ua': boston}],
        f: [{}, {'ua': boston}, {'new_york': seattle}, {'new_york': seattle, 'ua': boston}],
        g: [{}],
        h: [{}],
        i: [{}, {'los_angels': mg}],
    }

If you need to combine multiple such pre-defined dictionaries, you can create a helper function:

def combine_dicts(*d, **kw):
    """Combine dictionaries into one.

    Keys in later dictionaries override those in earlier dictionaries, with
    keyword arguments being applied last.

    """
    return reduce(lambda d1, d2: dict(d1, **d2), d + (kw,))

then use this with:

a = combine_dicts(base1, base2, {'some non-identifier key': 42}, r=3)

Upvotes: 3

jmetz
jmetz

Reputation: 12773

You only need a minimal change to your code:

m=(('p',1),)
a=dict(m, r=2)
b=dict(m, r=3)

Upvotes: 0

Related Questions