0

I am trying to create a dictionary that can be called upon for the respective data. My issue is that I have to account for case sensitivity in the user input. The dictionary is stored within the function main(). The goal of this program is for the user to be able to use the function's output (in this case stored in 'dict1') and enter keys to get the respective data. This is a simplified version of my program right now.

Due to restrictions in place, the user must use the Shell to assign the variable and c

def main(data_source_file):

    ### For sake of brevity, imagine I extract the data from the file and convert to a dict
    ### The final output is below

    dict1 = {'Africa': [1,2], 'Asia': [3,4], 'Americas', [5,6]}
    return dict1

>>> dict1 = main('datafile')
>>> dict1["Africa"]
[1,2]
>>> dict1["AFRICA"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'AFRICA'

I'm familiar with the idea of capitalisation in strings and lists, however I am unsure how to apply it to a key entry by the user.

My first thought was an approved entry list e.g. ["AFRICA","africa","Africa", (ect)] However I want to be able to account for inputs such as "AFriCA", so an approved list would take too long to write for each dictionary key.

Fourth
  • 3
  • 1
  • This question might be a better fit for [the software engineering stackexchange](https://softwareengineering.stackexchange.com) rather than here, since it's less about "how do I do [specific thing] in Python?" and more of a "how do I approach situations where user input needs to be treated case-insensitively?" – mtraceur May 19 '23 at 04:18
  • Not sure what your actual question is, but it seems like all you need is to normalize the input to some standard format, e.g. all lowercase. – Kache May 19 '23 at 04:32

2 Answers2

2

In general, if there are too many possibilities of valid input, the easiest and clearest approach is often to normalize the input before comparing it.

So for this problem, my first thought was to make sure that the keys are all-lowercase in the dictionary, and then I would lowercase the user's input before looking it up in the dictionary.

For serious solutions, also keep in mind that there are weird exceptions - in some languages, converting case sometimes changes letters, and some lower-case letters don't have an upper-case letter at all! So lowercasing is more robust than uppercasing, but the name for the idea we really want is called "case folding".

You can read more about this, and how to actually do it in Python, in these questions+answers:

How do I lowercase a string in Python?

How do I do a case-insensitive string comparison?


If you want the dictionary itself to "magically" behave case-insensitively, so that dict1["AfRiCa"] == dict1["africa"] == dict1["Africa"], what you really want is a custom object that does operator overloading to behave like a dictionary while doing the case-folding.

For example, you can create a dictionary subclass with methods overloaded to do case-folding. A bare-minimum example which will work for your question code:

import collections

class CaseInsensitiveDict(collections.abc.MutableMapping):
    def __init__(self, mapping):
        for key in mapping:
            self[key.casefold()] = mapping[key]
    def __getitem__(self, key):
        return super().__getitem__(key.casefold())
>>> dict1 = CaseInsensitiveDict({"Africa": [1,2], "Asia": [3,4]})
>>> dict1["africa"]
[1, 2]
>>> dict1["AfRiCa"]
[1, 2]

But for a proper complete solution that fully emulates a dict, you should also read:

How to properly subclass dict and override __getitem__ & __setitem__

How to check if type of a variable is string?

mtraceur
  • 3,254
  • 24
  • 33
0

here what you can do to solve this problem is to store the dictionary keys in either single case letters or uppercase letters by using the "lower()" or "upper()" function respectively.

def main(data_source_file):

    ### For sake of brevity, imagine I extract the data from the file and convert to a dict
    ### The final output is below

    dict1 = {'Africa'.lower(): [1,2], 'Asia'.lower(): [3,4], 'Americas'.lower(): [5,6]}
    return dict1

dict1 = main('datafile')
print(dict1["Africa".lower()])

Hope it helps :)