473,785 Members | 2,234 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Why are there no ordered dictionaries?

This is probably a FAQ, but I dare to ask it nevertheless since I
haven't found a satisfying answer yet: Why isn't there an "ordered
dictionary" class at least in the standard list? Time and again I am
missing that feature. Maybe there is something wrong with my programming
style, but I rather think it is generally useful.

I fully agree with the following posting where somebody complains why so
very basic and useful things are not part of the standard library:
http://groups.google.com/group/comp....52d2f771a49857

Are there plans to get it into the standard lib sometime?

-- Christoph
Nov 22 '05
210 10556
Bengt Richter schrieb:
d.setvalues(( 13, 14)) ==> d = OrderedDict((1, 13), (2, 14))
The implication above is that OrderedDict takes an *args argument,
but really it takes a single argument that is a sequence of k,v pairs,
(and maybe some keyword options).
Right. Interpret it as a short notation only, I did not want to change
the interface. I think it's a common mistake to forget the brackets
because you think one pair should be enough. At least I often forget it.
You could make keys, values, and items custom descriptors which would define __call__
for the old key() etc accesses, well as __getitem__ and __setitem__. Then you could write

d.items[0], d.items[-1] = d.items[-1], d.items[0]

to swap the order of the first and last items in the thing (I hesitate to say dict ;-)
You could also operate on slices.
Nice. You could also get the i-th value with d.values[i].

But is this considered good style or would it be considered "dirty" to
have a callable member that also supports indexing and slicing? (I don't
know, just asking?) Plus, it opens a can of worms by increasing the
complexity tremendously. Let's see whether this can be handled.
BTW, before I showed an example where d[2:3] returned
a new dict instance rather than d.items()[:]. I think the items list
is better, since they naturally add, sort, reverse, etc as lists,
and you can write OrderedDict(d[2:3]+d[1:2]) if you want a new dict.
Not sure about that. I would rather expect that if you slice an object,
you get an object of the same type. And you can also add, sort, reverse,
etc the ordered dict if you want.
A slice assignment to d[i:j] is really sugar for something, but we have to decide exactly
what in case of duplicate keys in the incoming items, either with each other ...
You mean slice assignments to d.items[i:j]. If you make the slice
assignment to d[i:j] then at least you cannot have conflicts in the
incoming items. The first question is: Should a slice assignment be
treated as deletion with subsequential addition (changing the order) or
as a replacement (i.e. try to not change the order)? I agree that the
second would be the expected semantics, but as you mentioned more
difficult to implement.
One way to define it would be
d.items[i:j] = itemseq

to be implemented as sugar for
newitems = d.items[:i] + list(itemseq) + d.items[j:]
d.clear()
d.update(newite ms)
Which should be the same as
d = OrderedDict(d.i tems[:i] + list(itemseq) + d.items[j:])
Sounds reasonable.
So
d.reverse()
could be spelled
d.items[:] = d.items[::-1]
Slice assignment for keys and values would also allow to set a new key
order with

d.keys[:] = newkeyseq

So no need to define a setkeys() method or let keys() take arguments.
If we want to allow this kind of things at all.
If you are using slices, you can safely use them directly in the __getitem__ of th dict interface,
as I did in the "Que mas?" post. So we don't have to write d.items[i:j] and could write d[i:j].
The thing is, d[i:j] will tempt to skip ".items" in d.items[i] and write d[i], which has the dict
key meaning, not the item list index. It is faster not have a descriptor between though.

I still think d[i:j] should return an ordered dict, not an item list.
I think maybe allowing write to keys or values is pretty iffy. There are too many weird
re-associations of keys and values possible, and which you could do my other means if you
really really wanted to. But I do think full index and slice read access would be fine.
There are different opinions. Fuzzyman would probably say "Don't trust
yourself?" I myself am undecided. Perhaps you could expect that somebody
knows what he does if he makes a slice assignment to d.keys. In any way,
such an assignment should not "break" the directory (with "broken" I
mean that the internal keys sequence does not match the keys of the
internal dictionary). If anything does not match, it should raise a
KeyException. If it is implemented that way, I think we can allow it.
I think also that d1==d2 should effectively be implemented as d1[:] == d2[:] -- i.e, compare
the item lists to implement comparisons.


Wouldn't it be more performant to compare for
d1.internal_dic t==d2.internal_ dict and
d1.internal_seq uence==d2.inter nal_sequence?
You don't keep track of the item lists, they need to be built on every
occasion.

-- Christoph
Nov 24 '05 #181
Fuzzyman schrieb:
d.keys() will still return a copy of the list, so d.keys()[i] will
still be slower than d.sequence[i]


Right, I forgot that. Bengt suggested to implement __call__ as well as
__getitem__ and __setitem__ for keys, values and items.

In this case, you could very effectively access it as d.values[i].

-- Christoph
Nov 24 '05 #182
"hacer" probablemente.

DCA.

Piet van Oostrum wrote:
>> Christoph Zwerschke <ci**@online.de > (CZ) escribió:

CZ> Eso es exactamente lo que yo queria haber!


¿Haber? ¿Tener? :=(
--
Piet van Oostrum <pi**@cs.uu.n l>
URL: http://www.cs.uu.nl/~piet [PGP 8DAE142BE17999C 4]
Private email: pi**@vanoostrum .org


Nov 25 '05 #183

Christoph Zwerschke wrote:
Fuzzyman schrieb:
d.keys() will still return a copy of the list, so d.keys()[i] will
still be slower than d.sequence[i]
Right, I forgot that. Bengt suggested to implement __call__ as well as
__getitem__ and __setitem__ for keys, values and items.

In this case, you could very effectively access it as d.values[i].


That means making keys, values, and items custom objects.
Creating a new instance would have the overhead of creating 4 new
objects instead of just 1. Is the added convenience worth it ? (Plus
the extra layers of method calls for each access).

I'm not sure. It's a nice idea in terms of using it (we could just
leave the sequence attribute as an alias for the new keys attribute -
for backwards compatibility).

All the best,

Fuzzyman
http://www.voidspace.org.uk/python/index.shtml
-- Christoph


Nov 25 '05 #184
Le ruego me perdone.

replace('haber' , random.choice(' tener', 'hacer', 'lograr'))

Mi espanol es peor que mi python.

-- Christoph
Nov 25 '05 #185
Sure - that was just an example of mutating the keys list without
having direct access to it.

If keys was implemented as an object (with a ``__call__`` method) then
we could also implement sequence methods on it - making it easier to
mutate the keys/values/items directly.

All the best,

Fuzzyman
http://www.voidspace.org.uk/python/index.shtml

Nov 25 '05 #186
Sure - that was just an example of mutating the keys list without
having direct access to it.

If keys was implemented as an object (with a ``__call__`` method) then
we could also implement sequence methods on it - making it easier to
mutate the keys/values/items directly.

All the best,

Fuzzyman
http://www.voidspace.org.uk/python/index.shtml

Nov 25 '05 #187

Alex Martelli wrote:
Fuzzyman <fu******@gmail .com> wrote:
There is already an update method of course. :-)

Slicing an ordered dictionary is interesting - but how many people are
actually going to use it ? (What's your use case)
I detest and abhor almost-sequences which can't be sliced (I consider
that a defect of collections.deq ue). If the ordered dictionary records
by its sequencing the time order of key insertion, being able to ask for
"the last 5 keys entered" or "the first 3 keys entered" seem to me to be
perfectly natural use cases, and most naturally accomplished by slicing
of course, d[-5:] and d[:3] respectively.


If you slice an ordered dictionary, I assume you would expect to get an
ordered dictionary back ?

Fuzzyman
http://www.voidspace.org.uk/python/index.shtml

Alex


Nov 25 '05 #188
Fuzzyman wrote:
That means making keys, values, and items custom objects.
Creating a new instance would have the overhead of creating 4 new
objects instead of just 1. Is the added convenience worth it ? (Plus
the extra layers of method calls for each access).
I'm not sure about that either. But since you are using odict for
convenience reasons anyway, and not for performance reasons, it would be
consequential. Performance testing should be made anyway, so this could
be tested as well. I think that creating these 3 additional objects will
not matter much if the dict has more than a handful of items. And the
extra layers will be only called if you really access these keys, values
or items attributes which will not happen very frequently. Normally, you
just loop over an ordered directory and acess keyed values.
I'm not sure. It's a nice idea in terms of using it (we could just
leave the sequence attribute as an alias for the new keys attribute -
for backwards compatibility).


Yes, you could make it a deprecated feature.

-- Christoph
Nov 25 '05 #189
Fuzzyman <fu******@gmail .com> wrote:
...
If you slice an ordered dictionary, I assume you would expect to get an
ordered dictionary back ?


That would be helpful, yes, though there are precedents for types whose
slicing doesn't return an instance of that type (e.g. slices of an mmap
are instances of str, not of mmap, if I recall correctly), most
sliceable sequences do follow that pattern.
Alex
Nov 25 '05 #190

This thread has been closed and replies have been disabled. Please start a new discussion.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.