Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Case insensitive dictionary search? [duplicate]

I can use map to implement the case insensitive list search with Python.

a = ['xyz', 'wMa', 'Pma'];  b = map(string.lower, a) if 'Xyz'.lower() in b:     print 'yes' 

How can I do the same thing with dictionary?

I tried the following code, but ap has the list of ['a','b','c'], not the case insensitive dictionary.

a = {'a':1, 'B':2, 'c':3} ap = map(string.lower, a) 
like image 555
prosseek Avatar asked Jul 21 '10 05:07

prosseek


2 Answers

Note that making a dictionary case-insensitive, by whatever mean, may well lose information: for example, how would you "case-insensitivize" {'a': 23, 'A': 45}?! If all you care is where a key is in the dict or not (i.e., don't care about what value corresponds to it), then make a set instead -- i.e.

theset = set(k.lower() for k in thedict) 

(in every version of Python, or {k.lower() for k in thedict} if you're happy with your code working only in Python 2.7 or later for the sake of some purely decorative syntax sugar;-), and check with if k.lower() in theset: ....

Or, you could make a wrapper class, e.g., maybe a read-only one...:

import collections  class CaseInsensitiveDict(collections.Mapping):     def __init__(self, d):         self._d = d         self._s = dict((k.lower(), k) for k in d)     def __contains__(self, k):         return k.lower() in self._s     def __len__(self):         return len(self._s)     def __iter__(self):         return iter(self._s)     def __getitem__(self, k):         return self._d[self._s[k.lower()]]     def actual_key_case(self, k):         return self._s.get(k.lower()) 

This will keep (without actually altering the original dictionary, so all precise information can still be retrieve for it, if and when needed) an arbitrary one of possibly-multiple values for keys that "collapse" into a single key due to the case-insensitiveness, and offer all read-only methods of dictionaries (with string keys, only) plus an actual_key_case method returning the actual case mix used for any given string key (or None if no case-alteration of that given string key matches any key in the dictionary).

like image 151
Alex Martelli Avatar answered Sep 20 '22 04:09

Alex Martelli


Using dict comprehensions (Python2.7+)

a_lower = {k.lower():v for k,v in a.items()} 

If your python is too old for dict comprehensions

a_lower = dict((k.lower(),v) for k,v in a.items()) 

then look up the value with the lowercase version of the key

value = a_lower[key.lower()] 
like image 44
John La Rooy Avatar answered Sep 19 '22 04:09

John La Rooy