[Tutor] SubDictionaries or am I reinventing a wheel?

Patrick K. O'Brien pobrien@orbtech.com
Tue, 12 Jun 2001 00:47:05 -0500


Imagine that you have a dictionary with a multipart key and you want to
extract a new dictionary that is a subset of the existing dictionary based
on matching a few of the leading elements that make up the key. For example,
GoldMine stores multiple record types in some of its database files. So I
have a dictionary with the table name and record type code as the key.

gmRecordTypes = {  # Table, Type, Description
    ('CAL', 'A'): 'Appointment',
    ('CAL', 'C'): 'Call back',
    ('CAL', 'D'): 'To-do',
    ('CAL', 'E'): 'Event',
    ('CAL', 'F'): 'Literature fulfillment',
    ('CAL', 'M'): 'Message',
    ('CAL', 'O'): 'Other',
    ('CAL', 'Q'): 'Queued e-mail',
    ('CAL', 'S'): 'Sales potential',
    ('CAL', 'T'): 'Next action',
    ('CONTHIST', 'A'): 'Appointment',
    ('CONTHIST', 'C'): 'Phone call',
    ('CONTHIST', 'D'): 'To-do',
    ('CONTHIST', 'E'): 'Event',
    ('CONTHIST', 'F'): 'Literature fulfillment',
    ('CONTHIST', 'L'): 'Form',
    ('CONTHIST', 'M'): 'Sent message',
    ('CONTHIST', 'O'): 'Other',
    ('CONTHIST', 'S'): 'Sale',
    ('CONTHIST', 'T'): 'Next action',
<snip>
    }

Now let's say I wanted a function that would return a new dictionary of just
the record types and descriptions for the CONTHIST table. Think of this as
sort of a query against a database table - select type, description from
gmRecordTypes where table = 'CONTHIST'. Imagine that you had lots of
dictionaries like this and that you wanted the function to be able to select
based on one matching element or several matching elements of the key. Well,
I did and here is what I came up with.

# partmatch can be a single value or any valid sequence for a dictionary key
or portion thereof.

def subDictionary(dictionary, partmatch=None):
    """Return a subset of a dictionary based on a partial key match."""
    if partmatch == None:
        return dictionary
    else:
        subd = {}
        partsize = len(partmatch)
        if partsize == 1:  # Reduce single element sequences to single
elements.
            partmatch = partmatch[0]
        for key in dictionary.keys():
            if partsize == 1:  # Reduce single element sequences to single
elements.
                keypart = key[0]
            else:
                keypart = key[:partsize]
            if keypart == partmatch:
                if len(key[partsize:]) == 1:  # Simplify the new key by
reducing it to a single object if possible.
                    newkey = key[partsize]
                else:
                    newkey = key[partsize:]
                subd[newkey] = dictionary[key]
        return subd

Now, I either came up with something nifty that will be useful to me and
maybe others, or I just spent a good couple of hours reinventing the wheel.
Does anyone know of any Python module that does this already? Is this a good
approach to the problem I described, or am I off my rocker? Somehow this
sort of manipulation seems like it should be part of the core of python in
the way that keys() and values() are already there.

---
Patrick K. O'Brien
Orbtech
"I am, therefore I think."