As far as the data structure, I taught myself how to use xml.dom. It turns out, I really like it. I see now why programmers are using it more for config files, etc.
I decided to develop my own class that acts sort of like a dictionary but can have multiple keys. Unlike a dictionary, it can have more then one key with the same value (but I designed the key() method will return only unique values).
Here is the code:
#! /usr/bin/python2.6
# -*- coding: utf-8 -*-
'''makes a new dictionary-type class
This class allows for multiple keys unlike the dictionary type.
The keys are past first as a list or tuple. Then, the data is to
be passed in a tuple or list of tuples or lists with the exact
number of data items per list/tuple.
Example:
>>> from superdict import SuperDict
>>> keynames = ['fname', 'lname', 'street', 'city', 'state', 'zip']
>>> names = [
... ['Jim', 'Smith', '123 Cherry St', 'Topeka', 'KS', '73135'],
... ['Rachel', 'West', '456 Bossom Rd', 'St Louis', 'MO', '62482']
... ]
>>> dictionary = SuperDict(keynames, names)
There is a SuperDict.keys method that shows all the keys for a given keyname
to be accessed as in:
>>> print dictionary.keys('city')
['Topeka', 'St Louis']
The add method is used to pass a list/tuple but must have the same number of
'fields'.
>>> dictionary.add(['John', 'Richards', '6 Tulip Ln', 'New Orleans', 'LA', '69231'])
The extend method is used to pass a multiple lists/tuples inside a list/tuple as above.
>>> new_names = [
['Randy', 'Young', '54 Palm Tree Cr', 'Honolulu', 'HA', '98352'],
['Scott', 'People', '31932 5th Ave', 'New York', 'NY', '03152']
]
>>> dictonary.extend(new_names)
The data attribute can be used to access the raw data as in:
>>> dictionary.data
[['Jim', 'Smith', '123 Cherry St', 'Topeka', 'KS', '73135'], ['Rachel', 'West', '456 Bossom Rd', 'St Louis', 'MO', '62482'], ['Randy', 'Young', '54 Palm Tree Cr', 'Honolulu', 'HA', '98352'], ['Scott', 'People', '31932 5th Ave', 'New York', 'NY', '03152']]
The data item is retrieved with the find method as below:
>>> dictionary.find('city', 'Topeka')
['Jim', 'Smith', '123 Cherry St', 'Topeka', 'KS', '73135']
What if there are more than one? Use the extended options of find to
find a second field as in:
>>> dictionary.find('city', 'Topeka', 'state', 'KS')
['Jim', 'Smith', '123 Cherry St', 'Topeka', 'KS', '73135']
To find all the fields that match, use findall (second keyname
is available for this just as in the find method):
>>> dictionary.find('city', 'Topeka')
[['Jim', 'Smith', '123 Cherry St', 'Topeka', 'KS', '73135'], ['Ralph', 'Johnson', '513 Willow Way', 'Topeka', 'KS', '73189']]
The delete method allows one to remove data, if needed:
>>> dictionary.delete(new_names[0])
>>> dictionary.data
[['Jim', 'Smith', '123 Cherry St', 'Topeka', 'KS', '73135'], ['Rachel', 'West', '456 Bossom Rd', 'St Louis', 'MO', '62482'], ['Scott', 'People', '31932 5th Ave', 'New York', 'NY', '03152']]
maintainer: <[email protected]>
LICENSE: GPL version 2
Copywrite 2010
'''
__version__ = 0.4
indexnames = ['city','state','zip','metar']
datasample = [
['Pawhuska', 'OK', '74056', 'KBVO'],
['Temple', 'TX', '76504', 'KTPL']
]
class SuperDict(object):
'''
superdict = SuperDict(keynames, data)
Keynames are a list/tuple of the entry names
Data is a list/tuple of lists/tuples containing the data1
All should be of the same length
See module doc string for more information
'''
def __init__(self, indexnames, data=None):
self.keydict = dict()
if data:
self.data = data
for index, name in enumerate(indexnames):
self.keydict[name.lower()] = index
def keys(self, index, sort=False):
'''
SuperDict.keys(keyname, sort=False)
Returns all the "keys" for the keyname(field name) but duplicates
are removed.
If sort=True, then the keys are sorted
'''
index = index.lower()
keynames = []
for item in self.data:
key = item[self.keydict[index]]
if key:
keynames.append(key)
keynames = list(set(keynames))
if sort:
keynames = sorted(keynames)
return keynames
def add(self, data):
'''
SuperDict.add(list/tuple)
adds another another entry into the dataset
'''
if self.data:
if not len(data) == len(self.data[0]):
print 'data length mismatch'
return
self.data.append(data)
def extend(self, data):
'''
SuperDict([list1, list2])
SuperDict((tuple1, tuple2))
Extends the dataset by more than one field at a time
'''
for datum in data:
self.add(datum)
def delete(self, data):
'''
SuperDict.delete(list/tuple)
Deletes an entry matching the list or tuple passed to the method
'''
# question for later: should I return true or false if something delete or not
for index, item in enumerate(self.data):
if data == item:
del self.data[index]
def find(self, keyname1, data1, keyname2=None, data2=None):
'''
SuperDict(keyname1, data1, keyname2=None, data2=None)
Look for the first entry based on the value of a keyname(s).
'''
keyname1 = keyname1.lower()
if keyname2:
keyname2 = keyname2.lower()
for item in self.data:
if data1 == item[self.keydict[keyname1]]:
if not data2:
return item
elif data2 == item[self.keydict[keyname2]]:
return item
def findall(self, keyname1, data1, keyname2=None, data2=None):
'''
SuperDict.findall(keyname1, data1, keyname2=None, data2=None)
'''
keyname1 = keyname1.lower()
if keyname2:
keyname2 = keyname2.lower()
items = []
for item in self.data1:
if data1 == item[self.keydict[keyname1]]:
if not data2:
items.append(item)
elif data2 == item[self.keydict[keyname2]]:
items.append(item)
return items