Elbert said:
Hi!
Here is the problem:
I have a dictionary. Keys are strings. How to make dictionary lookup
case insensitive?
In other words:
If dict = {'First":"Bob", "Last":"Tom"}, dict["first"] should return
"Bob"
Maybe dictionary is not the right data type? If so what is?
"""
More or less complete, you might want to add some more tests...
"""
import UserDict
import sys
import traceback
class CaseInsensitiveDict (dict, UserDict.UserDict, UserDict.DictMixin):
def __init__ (self, init=None, **kw):
if init is not None:
return super(CaseInsensitiveDict,
self).__init__(self.lowerDict(init), **kw)
return super(CaseInsensitiveDict, self).__init__(**kw)
def ifStrKey (cls, key):
if hasattr(key, 'lower'):
return key.lower()
return key
ifStrKey = classmethod(ifStrKey)
def lowerDict (cls, d):
# this handle's the case were d is a "mapping type"
# like (('foo','oof'), ('baz', 'zab'))
d = dict(d)
return dict([(k.lower(), v.lower()) for k in d.keys() for v in
d.values()])
lowerDict = classmethod(lowerDict)
def __contains__ (self, key):
return super(CaseInsensitiveDict,
self).__contains__(self.ifStrKey(key))
def get (self, key, default=None):
return super(CaseInsensitiveDict, self).get(self.ifStrKey(key),
default=default)
def pop (self, key, *args):
return super(CaseInsensitiveDict, self).pop(self.ifStrKey(key),
*args)
def setdefault (self, key, default):
return super(CaseInsensitiveDict, self).pop(self.ifStrKey(key),
default)
def __delitem__ (self, key):
return super(CaseInsensitiveDict,
self).__delitem__(self.ifStrKey(key))
def __getitem__ (self, key):
return super(CaseInsensitiveDict,
self).__getitem__(self.ifStrKey(key))
def __setitem__ (self, key, item):
return super(CaseInsensitiveDict,
self).__setitem__(self.ifStrKey(key), item)
def has_key (self, key):
return super(CaseInsensitiveDict,
self).has_key(self.ifStrKey(key))
def update (self, d):
return super(CaseInsensitiveDict, self).update(self.lowerDict(d))
def print_tb (e):
e_fmt = traceback.format_exception(e.__class__, e, sys.exc_traceback)
sys.stderr.write(''.join(e_fmt))
print
def test_d (d, k):
print `d`
print 'Key', `k`
try:
val = `d[k]`
print 'Value', val
except KeyError, e:
print 'Key failed'
print_tb(e)
print
if __name__ == '__main__':
td = {'FOO':'bar'}
d = CaseInsensitiveDict(td)
test_d(d, 'FOO')
d = CaseInsensitiveDict()
d.update(td)
test_d(d, 'FOO')
try:
# this should fail
d = CaseInsensitiveDict((('foo', 'oof',), ('zab',)))
except Exception, e:
print_tb(e)
d = CaseInsensitiveDict((('foo', 'oof',), ('zab', 'baz',)))
test_d(d, 'FOO')
d[object()] = 'bar'
print `d`