[Tutor] Why is an OrderedDict not sliceable?
Steven D'Aprano
steve at pearwood.info
Thu Jan 21 19:00:00 EST 2016
Further thoughts on your question...
On Wed, Jan 20, 2016 at 01:33:17PM +0000, Albert-Jan Roskam wrote:
> Hi,
>
> Like the subject says: Why is an OrderedDict not sliceable? (From the
> collections library). Was that an intentional omission, or a mistake?
> [1]
>
> Background: I do not use OrderedDict very often, but I thought I could
> use it to look up street and city names using postcodes ([0-9]{4}
> [a-z]{2} format). I needed it to be ordered because I also wanted to
> be able to use bisect, which is needed when the postcode letters are
> missing. In short: a fast dict lookup for complete postcodes and less
> fast bisect lookup for in complete postcodes.
I'm not sure I understand your use-case here.
You have postcodes that look like this:
"1234az"
Correct? Why do you want them *ordered*?
I think you are confusing OrderedDict for a "Sorted Dict". OrderedDict
doesn't keep the keys in sorted order, it keeps them in the order that
they were inserted. So unless you are super-careful to insert the
postcodes in sorted order, the order of them in the dict will be
whatever order you insert them:
py> from collections import OrderedDict
py> d = OrderedDict()
py> d['1234az'] = "1 Smith Street"
py> d['9999zz'] = "991203 Short Street"
py> d['3456mx'] = "24 Hour Lane"
py> for key in d:
... print(key, d[key])
...
1234az 1 Smith Street
9999zz 991203 Short Street
3456mx 24 Hour Lane
So even if OrderedDict supported slicing, that would not do what you
think it does.
Also, you have a problem -- what happens if the incomplete postcode is
missing the first digit? (I suppose for that case, you just have to do a
slow linear search.) What about transposed digits or other errors? I'm
glad I don't have to solve that problem!
Anyway, I suggest doing something like this:
(1) Keep the known postcodes in a regular dict, not an ordered dict.
(2) Once you have built the dict, then copy the keys and sort them:
postcodes = {
'1234az': "1 Smith Street",
'9999zz': "991203 Short Street",
'3456mx': "24 Hour Lane",
}
array = sorted(postcodes.keys())
(3) Each time you add a new postcode to the dict, use bisect to add it
to the array as well. To ensure you never forget, use a helper function:
def insert(postcode, entry):
if postcode in postcodes:
# deal with duplicate/existing key
...
else:
postcodes[postcode] = entry
bisect.insort(array, postcode)
Same for deleting.
--
Steve
More information about the Tutor
mailing list