pythondictionaryfor-looplist-comprehensiondictionary-comprehension

Python -- elegant dict comp where keys/values comes from sync'd lists?


I have a dictionary with two entries:

"triggers":[1, 4, 5, 9], 
"actions":[2, [1, 12, 13, 14], [1, 12, 13, 14], [3, 12, 13]]

Triggers correspond to actions -- so 1 corresponds to 2, 4 corresponds to the list [1,12,13,14], etc. I am trying to create a dictionary in which I flatten this and correspond the numbers to these two dictionaries:

ALARM_TRIGGER_EVENTS = {1: "SENSOR OPEN",
                        2: "MOTION DETECTED",
                        ...etc}
ALARM_ACTION_EVENTS = {1: "S-SOUND SIREN",
                       2: "SOUND BEEP",
                       ...etc}

So my ultimate dictionary should flatten the first two but replace the numbers with the corresponding event names in the last two dictionaries, something like this:

{"SENSOR OPEN":"SOUND BEEP", etc}

So far, I've been able to flatten the first two with this:

{trigger:self.alarmInfo["actions"][i] for i, trigger in \
    enumerate(self.alarmInfo["triggers"])}

(for reference, self.alarmInfo is a dictionary of the first set of lists)

So, two questions: 1) is there a more elegant way to accomplish the dictionary comprehension I just posted and 2) is there an elegant way to transform the numbers to the values so I end up with the preferred dictionary look I posted above? I keep thinking of ways, but they end up being incredibly hard to read and ugly. Thanks.


Solution

  • >>> d = {
    ...     'actions': [2, [1, 12, 13, 14], [1, 12, 13, 14], [3, 12, 13]],
    ...     'triggers': [1, 4, 5, 9],
    ... }
    >>> d_map = dict(zip(d['triggers'], d['actions']))
    >>> d_map = {k: [v] if isinstance(v, int) else v for k,v in d_map.items()}
    >>> d_map
    {1: [2], 4: [1, 12, 13, 14], 5: [1, 12, 13, 14], 9: [3, 12, 13]}
    

    Now you can write the comprehension:

    {TRIGGERS[k]: [ACTIONS(v) for v in vs] for k,vs in d_map.items()}