pete
pete

Reputation: 25091

Initialize a new dictionary from a tuple and the keys of another dictionary

I'm trying to build a dictionary using keys that come from [the values of] a tuple, and the value of those keys should be a new dictionary formed from the keys of a dictionary and the value of the sub-key initialized to 0.

The tuple looks like:

characters = ('Fred', 'Sam', 'Bob', 'Daisy', 'Gina', 'Rupert')

The dictionary involved looks like:

jobs = {
    'Pizzeria': 1,
    'Mall Kiosk': 2
    'Restaurant': 3
    'Burger Joint': 4
    'Department Store': 5
}

I'd like the final structure to look like:

jobsWorkedCounter = {
    'Fred': {
        'Pizzeria': 0,
        'Mall Kiosk': 0
        'Restaurant': 0
        'Burger Joint': 0
        'Department Store': 0
    },
    'Sam': {
        'Pizzeria': 0,
        'Mall Kiosk': 0
        'Restaurant': 0
        'Burger Joint': 0
        'Department Store': 0
    },

    ...

    'Rupert': {
        'Pizzeria': 0,
        'Mall Kiosk': 0
        'Restaurant': 0
        'Burger Joint': 0
        'Department Store': 0
    },
}

The end goal is to have a structure for incrementing counters:

jobsWorkedCounter['Fred']['Burger Joint'] += 1

I've tried using various nested comprehensions:

jobsWorkedCounter = { char: dict((key, 0) for key in jobs.keys()) for char in characters }

# and

jobsWorkedCounter = { char: dict(jobs.keys(), 0) for char in characters }

# and

jobsWorkedCounterDict = { key: 0 for key in jobs.keys() }
jobsWorkedCounter = { char: jobsWorkedCounterDict for char in characters }

# and

jobsWorkedCounter = { char: { key: 0 for key in jobs.keys() } for char in characters }

and a simple for loop:

jobsWorkedCounter = { char: {} for char in characters }
    for char in characters:
        jobsWorkedCounter[char] = dict.fromkeys(jobs.keys(), 0)

but the best I've been able to accomplish is a single sub-key instead of the full set:

jobsWorkedCounter = {
    'Fred': {
        'Pizzeria': 0,
    },
    'Sam': {
        'Pizzeria': 0,
    },

    ...

    'Rupert': {
        'Pizzeria': 0,
    },
}

It seems that no matter what I try, I'm managing to flatten the new dictionary down to a single key-value pair and that's what gets assigned to the key from the tuple.

How can I accomplish what I'm trying to do?

Also, just in case I'm doing this incorrectly as well, to check the output I'm doing this:

keys = jobsWorkedCounter['Fred'].keys()
raise Exception(keys)

which gets me:

Exception: [u'Pizzeria']

where I would expect to see:

Exception: [u'Pizzeria', u'Mall Kiosk', u'Restaurant', u'Burger Joint', u'Department Store']  

I'm fairly sure this method of seeing the keys should work because if I change it to:

keys = jobsWorkedCounter.keys()
raise Exception(keys)

I get:

Exception: [u'Fred', u'Sam', u'Bob', u'Daisy', u'Gina', u'Rupert']

Addendum

I'm stuck using Python 2.7 as I'm in a Ren'Py environment (hence the reason for raising an exception to see the output).

For example:

from pprint import pprint

gives me:

Import Error: No module named pprint

Upvotes: 0

Views: 2175

Answers (2)

norok2
norok2

Reputation: 26906

I created a new Ren'Py project (from Ubuntu 18.04) and added the following code at the beginning of screens.rpy. This is basically one of your tentatives:

init python:
    characters = ('Fred', 'Sam', 'Bob', 'Daisy', 'Gina', 'Rupert')

    jobs = {
        'Pizzeria': 1,
        'Mall Kiosk': 2,
        'Restaurant': 3,
        'Burger Joint': 4,
        'Department Store': 5
    }

    jobsWorkedCounter = {char: {key: 0 for key in jobs.keys()} for char in characters}
    keys = jobsWorkedCounter['Fred'].keys()
    raise Exception(keys)

And I get:

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/screens.rpy", line 5, in script
    init python:
  File "game/screens.rpy", line 19, in <module>
    raise Exception(keys)
Exception: [u'Department Store', u'Pizzeria', u'Restaurant', u'Mall Kiosk', u'Burger Joint']

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "game/screens.rpy", line 5, in script
    init python:
  File "/usr/share/games/renpy/renpy/ast.py", line 848, in execute
    renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store)
  File "/usr/share/games/renpy/renpy/python.py", line 1812, in py_exec_bytecode
    exec bytecode in globals, locals
  File "game/screens.rpy", line 19, in <module>
    raise Exception(keys)
Exception: [u'Department Store', u'Pizzeria', u'Restaurant', u'Mall Kiosk', u'Burger Joint']

Linux-4.15.0-55-generic-x86_64-with-Ubuntu-18.04-bionic
Ren'Py 6.99.14.1.3218
test_renpy 1.0
Wed Jul 24 21:03:28 2019

so, I would tend to think you have a bug somewhere else in your code.

Upvotes: 1

Andrej Kesely
Andrej Kesely

Reputation: 195553

Using dict comprehensions:

characters = ('Fred', 'Sam', 'Bob', 'Daisy', 'Gina', 'Rupert')

jobs = {
    'Pizzeria': 1,
    'Mall Kiosk': 2,
    'Restaurant': 3,
    'Burger Joint': 4,
    'Department Store': 5
}

jobsWorkedCounter = {c: {k: 0 for k in jobs} for c in characters}

# For pretty print:
#from pprint import pprint
#pprint(jobsWorkedCounter)

print(jobsWorkedCounter)

Prints:

{'Bob': {'Burger Joint': 0,
         'Department Store': 0,
         'Mall Kiosk': 0,
         'Pizzeria': 0,
         'Restaurant': 0},
 'Daisy': {'Burger Joint': 0,
           'Department Store': 0,
           'Mall Kiosk': 0,
           'Pizzeria': 0,
           'Restaurant': 0},
 'Fred': {'Burger Joint': 0,
          'Department Store': 0,
          'Mall Kiosk': 0,
          'Pizzeria': 0,
          'Restaurant': 0},
 'Gina': {'Burger Joint': 0,
          'Department Store': 0,
          'Mall Kiosk': 0,
          'Pizzeria': 0,
          'Restaurant': 0},
 'Rupert': {'Burger Joint': 0,
            'Department Store': 0,
            'Mall Kiosk': 0,
            'Pizzeria': 0,
            'Restaurant': 0},
 'Sam': {'Burger Joint': 0,
         'Department Store': 0,
         'Mall Kiosk': 0,
         'Pizzeria': 0,
         'Restaurant': 0}}

EDIT: Another, explicit version:

zeroed_jobs = dict((k, 0) for k in jobs)
jobsWorkedCounter = {c: dict(**zeroed_jobs) for c in characters}

print(jobsWorkedCounter)

Upvotes: 1

Related Questions