[Tutor] Why is an OrderedDict not sliceable?

Albert-Jan Roskam sjeik_appie at hotmail.com
Sun Jan 24 15:15:33 EST 2016


> Date: Fri, 22 Jan 2016 11:00:00 +1100
> From: steve at pearwood.info
> To: tutor at python.org
> Subject: Re: [Tutor] Why is an OrderedDict not sliceable?
> 
> 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:

You are right. See also my reply to Mark Lawrence, who made a similar remark.

> 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.


Oscar Benjamin's link about collections.OrderedDict.__eq__ (or rather, the fact that it's not reimplemented) scared the heck outta me :-)
Maybe this class should be avoided altogether?
 
> 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:

But I only *read* from the postcode table. I never insert any postcodes, nor do I delete any (ok, a few times a year I load new definitions from the database, because new houses, with new postcodes, will have been built).  See also my mail to Alan (today).

> 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
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor

 		 	   		  


More information about the Tutor mailing list