[Tutor] SubDictionaries or am I reinventing a wheel?
Roeland Rengelink
r.b.rigilink@chello.nl
Tue, 12 Jun 2001 14:23:29 +0200
"Patrick K. O'Brien" wrote:
Hi Patrick,
>
> 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',
<snip>
> }
>
Have you considered using nested dictionaries for this, i.e.:
gmRecordTypes = {'CAL': {'A': 'Appointment',
'C': 'Call back',
...
'T': 'Next action},
'CONTHIST': {'A':'Appointment',
'C': 'Call back',
...
'T': 'Next action'}}
You can then get at the subdictionaries through
subd = gmRecordTypes['CAL']
and individual values with
val = gmRecordTypes['CAL']['A']
This is sort of the standard approach for what you seem to describe.
> 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
Are you sure that subDictionary(dictionary) should return dictionary
itself,
while subDictionary(dictionary, ()) should return a copy?
> 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
>
Here's my somewhat more concise version.
Note that I also test if key and partmatch are of the same type.
def subDictionary(dictionary, partmatch=()):
"""Return a subset of a dictionary based on a partial key match."""
subd = {}
for key, val in dictionary.items():
if partial_match(partmatch, key):
newkey = key[len(partmatch):]
if len(newkey) == 1:
newkey = newkey[0]
subd[newkey] = val
return subd
def partial_match(first, second):
'''Match two sequences
returns 0 if type(first) != type(second)
returns 1 if second[:len(first)] == first
returns 0 otherwise
'''
if type(first) != type(second):
return 0
return second[:len(first)] == first
> 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?
Hey, your code works, which is the only practical definition of 'good
approach'
> 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.
>
This sounds like a nasty question, but think of it a an exercise.
Exactly what kind of manipulation do you mean? Remember keys() and
values() can be described exactly in one sentence only. Try to find the
one-sentence description for your proposed extensions. You could then
try building your own UserDict class that implements these manipulations
as additional methods.
Hope this helps,
Roeland
--
r.b.rigilink@chello.nl
"Half of what I say is nonsense. Unfortunately I don't know which half"