Этот вопрос уже имеет ответ здесь:
Я могу использовать карту для реализации нечувствительного к регистру поиска списка с Python.
a = ['xyz', 'wMa', 'Pma'];
b = map(string.lower, a)
if 'Xyz'.lower() in b:
print 'yes'
Как я могу сделать то же самое со словарем?
Я попробовал следующий код, но AP имеет список ['b', 'c'], не нечувствительный к регистру словарь.
a = {'a':1, 'B':2, 'c':3}
ap = map(string.lower, a)
Обратите внимание, что создание нечувствительного к регистру словаря каким бы то ни было образом может привести к потере информации: например, как бы вы «нечувствительны к регистру» {'a': 23, 'A': 45}
?! Если все, что вам нужно, это то, где находится ключ в dict или нет (т.е. не важно какое значение ему соответствует), тогда сделайте вместо него набор
, то есть
theset = set(k.lower() for k in thedict)
(в каждой версии из Python или {k.lower () для k в thedict}
, если вы довольны тем, что ваш код работает только в Python 2.7 или новее, ради чисто декоративного синтаксического сахара ;-), и проверьте с помощью , если k.lower () в диапазоне: ...
.
Или вы можете создать класс-оболочку, например, доступный только для чтения ...:
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())
Это сохранит (без фактического изменения исходного словаря, так что вся точная информация может быть получена для него, если и когда это необходимо) произвольное одно из возможных нескольких значений для ключей, которые "сворачиваются" в один ключ из-за к нечувствительности к регистру и предлагают все доступные только для чтения методы словарей (только со строковыми ключами) плюс метод actual_key_case
, возвращающий фактическое сочетание регистра, используемое для любого заданного строкового ключа (или None
, если регистр данного строкового ключа не соответствует ни одному ключу в словаре).
Использование dict-понимания (Python2.7 +)
a_lower = {k.lower():v for k,v in a.items()}
Если ваш Python слишком стар для понимания dict
a_lower = dict((k.lower(),v) for k,v in a.items())
, затем найдите значение с помощью строчной версии ключа
value = a_lower[key.lower()]
Если вам не нужен поиск очень часто, вы можете использовать эту функцию, не тратя место для другой копии словаря. Однако она медленная, так как каждый раз необходимо проверять все ключи.
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'
dict(zip(map(string.lower,a.keys()),a.values()))
сделает то, что вы ищете.
map (function, iterable) работает над итерируемым; а итерация словаря - это список ключей.
a = {'a': 1, 'c': 3, 'B': 2}
for i in a:
print a
# returns a c B
zip объединяет ключи и значения обратно в пары, но как серию кортежей. dict преобразует кортежи обратно в dict.
Вы также можете сделать что-нибудь вроде
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}
Или, что еще интереснее ...
dict(map(lambda (key, value):(string.lower(key),value),a.items()))