Ordered dictionaries?
Michal Wallace
sabren at manifestation.com
Thu Dec 13 17:36:35 EST 2001
On Thu, 13 Dec 2001, David Brady wrote:
> Hello,
>
> One last Perl module that I need to replace to
> complete my Python toolkit is a custom module that let
> me create a dictionary whose keys were settable and
> retrievable in a particular order. Essentially, this
> let us have a list whose ordered elements were also
> accessible by name.
>
> Has anyone done this? If not, what class operators
> would I need to override to create my own class that
> does this?
IdxDict from my zdc package is along these lines.
Code is below.
Cheers,
- Michal http://www.sabren.net/ sabren at manifestation.com
------------------------------------------------------------
Give your ideas the perfect home: http://www.cornerhost.com/
cvs - weblogs - php - linux shell - perl/python/cgi - java
------------------------------------------------------------
"""
an indexed dictionary (cross between list and dict)
"""
__ver__="$Id: IdxDict.py,v 1.5 2001/01/02 02:00:59 sabren Exp $"
import UserDict
class IdxDict(UserDict.UserDict):
__super = UserDict.UserDict
def __init__(self):
self.__super.__init__(self)
self.idx = []
def _toStringKey(self, key):
"""Convert numeric keys into string keys. Leaves string keys as is"""
# handle numeric keys:
if type(key)==type(0):
if not (0 <= key < len(self.idx)):
## oddly enough, it is this IndexError here
## that allows you to do "for x in myIdxDict:"
raise IndexError, `key` + " is out of bounds."
# convert it to a string key
key = self.idx[key]
return key
def __setitem__(self, key, item):
"""
we can only use a numeric key if it's bigger than
the length of the index..
eg,after:
>>> idx['a'] = 'abc'
idx[0] now maps to "a", so:
>>> idx[0] = 'xyz'
is a reassignment. BUT:
>>> idx[1] = 'efg'
is a normal assignment.
To handle the magic of figuring out the last index, use 'append':
>>> idx.append('hijk')
>>> idx.keys()
['a', 1, 2]
>>> idx[2]
'hijk'
"""
if (type(key) == type(0)) and (key < len(self.idx)):
key = self._toStringKey(key)
if not key in self.idx:
self.idx.append(key)
self.data[key] = item
def __getitem__(self, key):
key = self._toStringKey(key)
return self.data[key]
def __repr__(self):
res = "{"
for key in self.idx:
res = res + repr(key) + ": " + repr(self.data[key]) + ", "
# strip that last comma and space:
if len(res) > 1:
res = res[:-2]
res = res + "}"
return res
#### these are so we can treat it like its a list ######
def __len__(self):
return len(self.idx)
def clear(self):
self.__super.clear(self)
self.idx = []
def __getslice__(self, i, j):
i = max(i, 0); j = max(j, 0)
res = []
for item in self.idx[i:j]:
res.append(self.data[item])
return res
def append(self, other):
self[len(self.idx)]=other
### .. or like a dictionary: #########
def keys(self):
return self.idx
def values(self):
return self[:]
### << is a magical append operator ##########
def __lshift__(self, other):
self.append(other)
#@TODO: what should __delitem__ do??
# I'm not going to worry about it now, because
# I don't need to delete anything from my lists.
More information about the Python-list
mailing list