不区分大小写的字典

109 投票
12 回答
104506 浏览
提问于 2025-04-15 18:07

我想让我的字典不区分大小写。

我有这个示例代码:

text = "practice changing the color"

words = {'color': 'colour',
        'practice': 'practise'}

def replace(words,text):

    keys = words.keys()

    for i in keys:
        text= text.replace(i ,words[i])
    return  text

text = replace(words,text)

print text

输出是:练习改变颜色

我希望另一个字符串,"practice changing the Color"(其中Color是大写开头),也能得到相同的输出。

我相信有一种通用的方法可以把字母转换成小写,使用mydictionary[key.lower()],但我不太确定怎么把这个方法最好地融入到我现有的代码中。(如果这真的是一个合理且简单的方法的话)。

12 个回答

88

目前被接受的答案在很多情况下都不适用,所以不能直接用来替代dict。要想做好一个合适的dict替代品,有几个棘手的问题需要解决:

  • 需要重载所有涉及键的方法
  • 要正确处理非字符串类型的键
  • 要妥善处理这个类的构造函数

下面的代码应该会好很多:

class CaseInsensitiveDict(dict):
    @classmethod
    def _k(cls, key):
        return key.lower() if isinstance(key, basestring) else key

    def __init__(self, *args, **kwargs):
        super(CaseInsensitiveDict, self).__init__(*args, **kwargs)
        self._convert_keys()
    def __getitem__(self, key):
        return super(CaseInsensitiveDict, self).__getitem__(self.__class__._k(key))
    def __setitem__(self, key, value):
        super(CaseInsensitiveDict, self).__setitem__(self.__class__._k(key), value)
    def __delitem__(self, key):
        return super(CaseInsensitiveDict, self).__delitem__(self.__class__._k(key))
    def __contains__(self, key):
        return super(CaseInsensitiveDict, self).__contains__(self.__class__._k(key))
    def has_key(self, key):
        return super(CaseInsensitiveDict, self).has_key(self.__class__._k(key))
    def pop(self, key, *args, **kwargs):
        return super(CaseInsensitiveDict, self).pop(self.__class__._k(key), *args, **kwargs)
    def get(self, key, *args, **kwargs):
        return super(CaseInsensitiveDict, self).get(self.__class__._k(key), *args, **kwargs)
    def setdefault(self, key, *args, **kwargs):
        return super(CaseInsensitiveDict, self).setdefault(self.__class__._k(key), *args, **kwargs)
    def update(self, E={}, **F):
        super(CaseInsensitiveDict, self).update(self.__class__(E))
        super(CaseInsensitiveDict, self).update(self.__class__(**F))
    def _convert_keys(self):
        for k in list(self.keys()):
            v = super(CaseInsensitiveDict, self).pop(k)
            self.__setitem__(k, v)
89

顺便说一下,我在Requests上发现了一个很棒的实现:

https://github.com/kennethreitz/requests/blob/v1.2.3/requests/structures.py#L37

49

如果我理解得没错,你想要一种方法,让字典的键不区分大小写。一个办法是创建一个新的字典类,并重写设置和获取键值的方式:

class CaseInsensitiveDict(dict):
    def __setitem__(self, key, value):
        super(CaseInsensitiveDict, self).__setitem__(key.lower(), value)

    def __getitem__(self, key):
        return super(CaseInsensitiveDict, self).__getitem__(key.lower())

撰写回答