¿Búsqueda del diccionario insensible del caso?

Puedo usar el mapa para implementar la búsqueda de listas que no distingue entre mayúsculas y minúsculas con Python.

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

¿Cómo puedo hacer lo mismo con el diccionario?

Probé el siguiente código, pero ap tiene la lista de [‘a’, ‘b’, ‘c’], no el diccionario que no distingue entre mayúsculas y minúsculas.

 a = {'a':1, 'B':2, 'c':3} ap = map(string.lower, a) 

Tenga en cuenta que hacer que un diccionario no distinga entre mayúsculas y minúsculas, por cualquier medio, puede perder información: por ejemplo, ¿cómo “insensibilizaría las mayúsculas y minúsculas” {'a': 23, 'A': 45} ?! Si todo lo que te importa es donde una clave está en el dict o no (es decir, no importa qué valor le corresponde), entonces set un set lugar, es decir

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

(en todas las versiones de Python, o {k.lower() for k in thedict} si está contento con que su código funcione solo en Python 2.7 o posterior por el bien de una syntax decorativa de azúcar ;-), y verifique con if k.lower() in theset: ...

O bien, podría hacer una clase de envoltorio, por ejemplo, tal vez una de solo lectura …:

 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()) 

Esto mantendrá (sin alterar realmente el diccionario original, por lo que aún se puede recuperar toda la información precisa, si es necesario, cuando sea necesario) uno arbitrario de posibles valores múltiples para las claves que se “colapsan” en una sola clave debido al caso. insensibilidad, y ofrece todos los métodos de solo lectura de los diccionarios (solo con claves de cadena) más un método actual_key_case que devuelve la combinación de mayúsculas y minúsculas utilizada para cualquier clave de cadena dada (o None si no hay ninguna modificación de mayúsculas y minúsculas en esa clave de cadena dada) el diccionario).

Usando las comprensiones de dict (Python2.7 +)

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

Si tu python es demasiado viejo para comprender el dictado

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

luego busque el valor con la versión en minúscula de la clave

 value = a_lower[key.lower()] 

Comience a usar un diccionario que no distingue entre mayúsculas y minúsculas a través de

 from requests import CaseInsensitiveDict 

O si quieres ver el código:

 class CaseInsensitiveDict(dict): """Basic case insensitive dict with strings only keys.""" proxy = {} def __init__(self, data): self.proxy = dict((k.lower(), k) for k in data) for k in data: self[k] = data[k] def __contains__(self, k): return k.lower() in self.proxy def __delitem__(self, k): key = self.proxy[k.lower()] super(CaseInsensitiveDict, self).__delitem__(key) del self.proxy[k.lower()] def __getitem__(self, k): key = self.proxy[k.lower()] return super(CaseInsensitiveDict, self).__getitem__(key) def get(self, k, default=None): return self[k] if k in self else default def __setitem__(self, k, v): super(CaseInsensitiveDict, self).__setitem__(k, v) self.proxy[k.lower()] = k 
 dict(zip(map(string.lower,a.keys()),a.values())) 

Hará lo que estés buscando.

mapa (función, iterable) trabaja sobre lo iterable; E iterable del diccionario es la lista de claves.

 a = {'a': 1, 'c': 3, 'B': 2} for i in a: print a # returns ac B 

zip reúne las claves y los valores de nuevo en pares, pero como una serie de tuplas. dict convierte las tuplas de nuevo en un dict.

También podrías hacer algo como

 def myfunc(t): return (string.lower(t[0]),t[1]) map(myfunc,a.items()) # returns [('a', 1), ('c', 3), ('b', 2) dict(map(myfunc,a.items())) # returns {'a': 1, 'c': 3, 'b': 2} 

O, aún más divertido …

 dict(map(lambda (key, value):(string.lower(key),value),a.items())) 

Si no necesita la búsqueda con mucha frecuencia, puede usar esta función sin perder espacio para otra copia del diccionario. Sin embargo, es lento ya que todas las teclas deben ser revisadas cada vez.

 a = {'xyz':2, 'wMa':8, 'Pma':9} ## if you do not use many times and/or the dict is very big def case_insensitive_key(a,k): k = k.lower() return [a[key] for key in a if key.lower() == k] print 'yes' if case_insensitive_key(a,'Xyz') else 'no' 

Solo quería agregar __setitem__, pop a la Respuesta de Alex Martelli:

 from collections import Mapping class CaseInsensitiveDict(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 __setitem__(self, k, v): self._d[k] = v self._s[k.lower()] = k def pop(self, k): k0 = self._s.pop(k.lower()) return self._d.pop(k0) def actual_key_case(self, k): return self._s.get(k.lower())