Dictionary order causing input result to change?
Question: New here, and very new to Python. Go easy on me. I've got a .bat which allows
a user to enter an IP or hostname which if valid will ping the target and then
allow some actions to be performed. However, it's fairly inflexible and I
think I've reached the limit of what I can do with that method. I decided to
make the same script but in python to allow for a more flexible approach,
where multiple criteria could be defined via dictionarys, rather than have the
user enter them one by one which will hopefully avoid user error/typos.

I've finished the first step of the code, which is asking the user for a
keyword, checking it against one of the dictionaries, which if correct sets
some criteria and allows the user to proceed to entering their IP.

My problems are: 1\. Depending which order the dictionary prints in, will
depend what keywords are accepted. For example, if the dictionary prints in
the order;

    
    
    {'TestGame': ['test', 'testing', 'tst'], 'ZestGame': ['zest', 'zesting', 'zst']}
    

then the script will only accept the words test, testing or tst. The opposite
will apply if 'Zestgame' prints first.

and 2. If the user enters a word that is not allowed, it should display the
message

    
    
    The project or game you entered was not recognised.
    

Then loop round to ask them to enter a valid keyword. However it skips the
above message and immediatley asks the user to

    
    
    Enter your PROJECT or GAME
    

Any ideas or solutions to these?

Full code:

    
    
    import os, sys, ipaddress
    
    # Allowed Project names with related keywords.
    Projects = {
        "ZestGame":     ['zest', 'zesting', 'zst'],
        "TestGame":     ["test", "testing", "tst"]}
    print(Projects)
    # Email format tied to Project
    ProjectEmails = {
        "ZestGame":     "zsti-zesty",
        "TestGame":     "tsti-testy"}
    # Unique 32 character ID.
    ProjectSCIDs = {
    "ZestGame":     "246zesty810scid12141618202224262",
    "TestGame":     "123testy456scid78910111213141516"}
    # Step 1 Start - Set ActiveProject and associated information.
    InputResult = "NOTFOUND"
    while True:
        if InputResult == "Valid":
            break
        ActiveProject = "NOTFOUND"
        ActiveProject = "NOTFOUND"
        ActiveSCID = "NOTFOUND"
        UserInput = input("Enter your PROJECT or GAME:\n")
    # Checks UserInput against Projects dictionary, loops if invalid.
    for key, val in Projects.items():
        if UserInput.lower() in val:
            ActiveProject = key
    # Sets ActiveProject, ActiveEmail and ActiveSCID if UserInput input result was OK.
        for key, val in ProjectEmails.items():
            if ActiveProject in key:
                ActiveEmail = (val+"@email.com")
        for key, val in ProjectSCIDs.items():
            if ActiveProject in key:
                ActiveSCID = val
                InputResult = "Valid"
            break
        else:
            print("The project or game you entered was not recognised.")
            InputResult = "NOTFOUND"
    print("\nThe user selected "+ActiveProject)
    print(ActiveEmail+" "+ActiveSCID)
    


Answer: Keep in mind that Python dics are not ordered, change your code and use
[OrdererDict](https://docs.python.org/2/library/collections.html#collections.OrderedDict)
wich uses the insertion order

Let me add an example:

    
    
    >>> d = {k:v for k,v in zip("asdfghjkl", range(10))}
    >>> d
    {'a': 0, 'd': 2, 'g': 4, 'f': 3, 'h': 5, 'k': 7, 'j': 6, 'l': 8, 's': 1}
    
    >>> od = OrderedDict(zip("asdfghjkl", range(10)))
    >>> od
    OrderedDict([('a', 0), ('s', 1), ('d', 2), ('f', 3), ('g', 4), ('h', 5), ('j', 6), ('k', 7), ('l', 8)])
    

Notice how the `'s'` key in the first dict is in the "last position" of it,
but in the ordered dict it is in the "second position" as it should by
insertion.

For checking if the user input is in any of the dictionaries just use
`.has_key(ActiveProject)` method in that dictionaries

Examples:

checking 1 dict:

    
    
    if not Projects.has_key(ActiveProject):
        print "The project or game you entered was not recognised."
    

checking for all dicts:

    
    
    if not any(map(lambda x: x.has_key(ActiveProject), [Projects, ProjectEmails])):
        print "The project or game you entered was not recognised."
    else:
        do whatever
    

