On 25 Sep, 20:28, Paul Hankin <[EMAIL PROTECTED]> wrote:
> On Sep 25, 7:58 pm, Steven Bethard <[EMAIL PROTECTED]> wrote:
>
>
>
> > > Paul Hankin wrote:
> > > ...
> > > class sorteddict(dict):
> > > "A sorted dictionary"
> > > def __init__(self, arg=None, cmp=None, key=None, reverse=False):
> > > if arg:
> > > ...
>
> > With this is the implementation, I'm definitely -1. Not because it's a
> > bad implementation, but because if the iteration is always doing a sort,
> > then there's no reason for a separate data structure. Just use sorted()
> > directly on a regular dict. That has the advantage of being much more
> > obvious about where the expensive operations are::
>
> > for key in sorted(d, ...):
> > ... whatever you want to do ...
>
> > IMHO, the only reason to introduce a sorteddict() is if it minimizes the
> > cost of sorting the keys.
>
> I disagree with your reason for introducing a sorteddict - the main
> reason should be if it makes code that uses it simpler and more
> readable, with efficiency (within reasonable limits) being of
> secondary importance. Unfortunately for sorteddict, your code is
> simpler and more explicit for most obvious use cases.
>
> But, with Bill's cached sorted key list it'll be reasonably efficient,
> and it's likely possible to update the sorted cache more efficiently
> than resorting if there's only been a small number of insertions since
> the last sort, but I haven't the time to do a thorough job.
>
> --
> Paul Hankin
I think that keeping a sorted list of keys is worthwhile, but because
the key or cmp functions could access keys or values or both you have
to invalidate whenever a key or value is added or changed. Here's my
version (v. similar to yours of course, but sorting when necessary):
class sorteddict(dict):
def __init__(self, iterable=None, cmp=None, key=None,
reverse=False):
if iterable is None:
iterable = []
dict.__init__(self, iterable)
self.__cmp = cmp
self.__key = key
self.__reverse = reverse
self.__keys = None
def update(self, *args, **kwargs):
dict.update(self, *args, **kwargs)
self.__keys = None
@classmethod
def fromkeys(cls, iterable, value=None):
dictionary = cls()
for key in iterable:
dictionary[key] = value
return dictionary
def copy(self):
dictionary = sorteddict(dict.copy(self), cmp=self.__cmp,
key=self.__key,
reverse=self.__reverse)
dictionary.__keys = None if self.__keys is None else
self.__keys[:]
return dictionary
def clear(self):
self.__keys = None
dict.clear(self)
def setdefault(self, key, value):
self.__keys = None
return dict.setdefault(self, key, value)
def pop(self, key, value=None):
if key not in self:
return value
self.__keys = None
return dict.pop(self, key, value)
def popitem(self):
self.__keys = None
return dict.popitem(self)
def keys(self):
if self.__keys is None:
self.__keys = sorted(dict.keys(self), cmp=self.__cmp,
key=self.__key,
reverse=self.__reverse)
return self.__keys[:]
def values(self):
if self.__keys is None:
self.__keys = sorted(dict.keys(self), cmp=self.__cmp,
key=self.__key,
reverse=self.__reverse)
return [self[key] for key in self.__keys]
def items(self):
if self.__keys is None:
self.__keys = sorted(dict.keys(self), cmp=self.__cmp,
key=self.__key,
reverse=self.__reverse)
return [(key, self[key]) for key in self.__keys]
def __iter__(self):
if self.__keys is None:
self.__keys = sorted(dict.keys(self), cmp=self.__cmp,
key=self.__key,
reverse=self.__reverse)
return iter(self.__keys)
def iterkeys(self):
if self.__keys is None:
self.__keys = sorted(dict.keys(self), cmp=self.__cmp,
key=self.__key,
reverse=self.__reverse)
return iter(self.__keys)
def itervalues(self):
if self.__keys is None:
self.__keys = sorted(dict.keys(self), cmp=self.__cmp,
key=self.__key,
reverse=self.__reverse)
for key in self.__keys:
yield self[key]
def iteritems(self):
if self.__keys is None:
self.__keys = sorted(dict.keys(self), cmp=self.__cmp,
key=self.__key,
reverse=self.__reverse)
for key in self.__keys:
yield key, self[key]
def __delitem__(self, key):
self.__keys = None
dict.__delitem__(self, key)
def __setitem__(self, key, value):
self.__keys = None
dict.__setitem__(self, key, value)
def __repr__(self):
return str(self)
def __str__(self):
if self.__keys is None:
self.__keys = sorted(dict.keys(self), cmp=self.__cmp,
key=self.__key,
reverse=self.__reverse)
return "{%s}" % ", ".join(
["%r: %r" % (key, self[key]) for key in self.__keys])
--
http://mail.python.org/mailman/listinfo/python-list