Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Case insensitive dictionary

Tags:

python

I'd like my dictionary to be case insensitive.

I have this example code:

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

Output = practise changing the colour

I'd like another string, "practice changing the Color", (where Color starts with a capital) to also give the same output.

I believe there is a general way to convert to lowercase using mydictionary[key.lower()] but I'm not sure how to best integrate this into my existing code. (If this would be a reasonable, simple approach anyway).

like image 376
Kim Avatar asked Jan 17 '10 18:01

Kim


People also ask

How do you make a dictionary case-insensitive?

In the Dictionary constructor you can specify how keys are compared. For string keys, the default is a case sensitive comparison. To make it case insensitive, you can pass in StringComparer. InvariantCultureIgnoreCase.

Is dictionary in Python case sensitive?

A Python dictionary sub-class that is case-insensitive when searching, but also preserves the keys as inserted. when keys are listed, ie, via keys() or items() methods. pair as the key's value (values become dictionaries).

Is Dictionary Containskey case sensitive C#?

The default constructor of C# Dictionary class constructs a Dictionary object, in which the keys are case sensitive. So when you insert data pairs <Key, Value> and <key, Value>, they are regarded as two different items.

Are Keys in Python case sensitive?

Dictionary Keys Are Case-Sensitive : Dictionary Key « Dictionary « Python.


2 Answers

The currently accepted answer wouldn't work for lots of cases, so it cannot be used as a drop-in dict replacement. Some tricky points in getting a proper dict replacement:

  • overloading all of the methods that involve keys
  • properly handling non-string keys
  • properly handling the constructor of the class

The following should work much better:

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)
like image 177
m000 Avatar answered Oct 19 '22 18:10

m000


Just for the record. I found an awesome impementation on Requests:

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

like image 78
santiagobasulto Avatar answered Oct 19 '22 20:10

santiagobasulto