Нечувствительный к регистру поиск словаря? [дубликат]

Этот вопрос уже имеет ответ здесь:

Я могу использовать карту для реализации нечувствительного к регистру поиска списка с 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)
27
задан martineau 17 February 2018 в 19:21
поделиться

4 ответа

Обратите внимание, что создание нечувствительного к регистру словаря каким бы то ни было образом может привести к потере информации: например, как бы вы «нечувствительны к регистру» {'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 , если регистр данного строкового ключа не соответствует ни одному ключу в словаре).

37
ответ дан 28 November 2019 в 04:25
поделиться

Использование 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()]
16
ответ дан 28 November 2019 в 04:25
поделиться

Если вам не нужен поиск очень часто, вы можете использовать эту функцию, не тратя место для другой копии словаря. Однако она медленная, так как каждый раз необходимо проверять все ключи.

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'
3
ответ дан 28 November 2019 в 04:25
поделиться
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()))
5
ответ дан 28 November 2019 в 04:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: