不区分大小写的字典

我希望我的字典不区分大小写。

我有这个例子代码:

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 

输出=练习改变颜色

我想要另一个string“ 改变颜色 ”(其中“颜色”以大写字母开始)也给出相同的输出。

我相信有一个通用的方法来使用mydictionary[key.lower()]转换为小写,但我不知道如何最好地将其整合到我现有的代码。 (如果这将是一个合理的,简单的方法)。

如果我正确地理解了你,并且你想要一种不区分大小写的方式来键入字典,一种方法是将字典进行子类化并重载setter / getter:

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

只是为了logging。 我发现一个很好的要求 :

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

目前批准的答案不适用于很多情况下,所以它不能作为一个dictreplace。 在得到一个正确的dictreplace一些棘手的问题:

  • 重载所有涉及密钥的方法
  • 正确处理非string键
  • 正确处理类的构造函数

以下应该会更好:

 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) 

你会考虑在你的input上使用string.lower()并使用一个完全小写的字典吗? 这是一个hacky解决scheme,但它的作品

在我的特殊情况下,我需要不区分大小写的查找,但是,我不想修改密钥的原始大小写。 例如:

 >>> d = {} >>> d['MyConfig'] = 'value' >>> d['myconfig'] = 'new_value' >>> d {'MyConfig': 'new_value'} 

您可以看到该字典仍然具有原始密钥,但是它不区分大小写。 这是一个简单的解决scheme:

 class CaseInsensitiveKey(object): def __init__(self, key): self.key = key def __hash__(self): return hash(self.key.lower()) def __eq__(self, other): return self.key.lower() == other.key.lower() def __str__(self): return self.key 

获取和设置字典中的条目都需要__hash__和__eq__覆盖。 这是创build密钥散列到字典中的相同位置,如果他们不区分大小写均等。

现在要么创build一个自定义字典,使用提供的键来初始化一个CaseInsensitiveKey:

 class CaseInsensitiveDict(dict): def __setitem__(self, key, value): key = CaseInsensitiveKey(key) super(CaseInsensitiveDict, self).__setitem__(key, value) def __getitem__(self, key): key = CaseInsensitiveKey(key) return super(CaseInsensitiveDict, self).__getitem__(key) 

或者只要确保在使用字典时始终传递CaseInsensitiveKey的实例作为键。

虽然不区分大小写的字典是一个解决scheme,并有答案如何实现,在这种情况下有一个可能更简单的方法。 不区分大小写的search就足够了:

 import re text = "Practice changing the Color" words = {'color': 'colour', 'practice': 'practise'} def replace(words,text): keys = words.keys() for i in keys: exp = re.compile(i, re.I) text = re.sub(exp, words[i], text) return text text = replace(words,text) print text