不区分大小写的字典搜索?

54 投票
6 回答
109286 浏览
提问于 2025-04-16 01:36

我可以用map来实现不区分大小写的列表搜索,使用Python。

a = ['xyz', 'wMa', 'Pma'];

b = map(string.lower, a)
if 'Xyz'.lower() in b:
    print 'yes'

那我怎么用字典来做同样的事情呢?

我试了下面的代码,但ap得到的是['a','b','c']这个列表,而不是不区分大小写的字典。

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

6 个回答

28

使用字典推导式(Python2.7及以上版本)

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

如果你的Python版本太旧,不支持字典推导式

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

那么可以用小写字母的键来查找对应的值

value = a_lower[key.lower()]
30

开始使用一个真正不区分大小写的字典,可以通过以下方式:

from requests.structures import CaseInsensitiveDict

如果你想看看代码的话:

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
55

注意,通过任何方式让字典不区分大小写,可能会丢失一些信息:比如,你怎么处理这个字典 {'a': 23, 'A': 45} 呢?如果你只关心某个键在字典里是否存在(也就是说,不在乎它对应的值是什么),那么不如直接用一个 set,也就是:

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

(在所有版本的Python中都可以用,或者如果你只想让代码在Python 2.7及以后版本工作,可以用 {k.lower() for k in thedict},这样只是为了让代码看起来更好看;-),然后用 if k.lower() in theset: ... 来检查。)

另外,你也可以做一个包装类,比如,可能是一个只读的...:

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

撰写回答