How to make replacement in python's dict?
Question: The goal I want to achieve is to exchange all items whose form is
`#item_name#` to the from `(item_value)` in the dict. I use two `dict` named
`test1` and `test2` to test my function. Here is the code:

    
    
    test1={'integer_set': '{#integer_list#?}', 'integer_list': '#integer_range#(?,#integer_range#)*', 'integer_range': '#integer#(..#integer#)?', 'integer': '[+-]?\\d+'}
    test2={'b': '#a#', 'f': '#e#', 'c': '#b#', 'e': '#d#', 'd': '#c#', 'g': '#f#', 'a': 'correct'}
    def change(pat_dict:{str:str}):
        print('Expanding: ',pat_dict)
        num=0
        while num<len(pat_dict):
            inv_pat_dict = {v: k for k, v in pat_dict.items()}
            for value in pat_dict.values():
                for key in pat_dict.keys():
                    if key in value:
                        repl='#'+key+'#'
                        repl2='('+pat_dict[key]+')'
                        value0=value.replace(repl,repl2)
                        pat_dict[inv_pat_dict[value]]=value0 
            num+=1
        print('Result: ',pat_dict)    
    
    change(test1)
    change(test2)
    

sometimes I can get correct result like:

    
    
    Expanding:  {'integer': '[+-]?\\d+', 'integer_list': '#integer_range#(?,#integer_range#)*', 'integer_set': '{#integer_list#?}', 'integer_range': '#integer#(..#integer#)?'}
    Result:  {'integer': '[+-]?\\d+', 'integer_list': '(([+-]?\\d+)(..([+-]?\\d+))?)(?,(([+-]?\\d+)(..([+-]?\\d+))?))*', 'integer_set': '{((([+-]?\\d+)(..([+-]?\\d+))?)(?,(([+-]?\\d+)(..([+-]?\\d+))?))*)?}', 'integer_range': '([+-]?\\d+)(..([+-]?\\d+))?'}
    Expanding:  {'c': '#b#', 'f': '#e#', 'e': '#d#', 'b': '#a#', 'g': '#f#', 'd': '#c#', 'a': 'correct'}
    Result:  {'c': '((correct))', 'f': '(((((correct)))))', 'e': '((((correct))))', 'b': '(correct)', 'g': '((((((correct))))))', 'd': '(((correct)))', 'a': 'correct'}
    

But most of time I get wrong results like that:

    
    
    Expanding:  {'integer_range': '#integer#(..#integer#)?', 'integer': '[+-]?\\d+', 'integer_set': '{#integer_list#?}', 'integer_list': '#integer_range#(?,#integer_range#)*'}
    Result:  {'integer_range': '([+-]?\\d+)(..([+-]?\\d+))?', 'integer': '[+-]?\\d+', 'integer_set': '{(#integer_range#(?,#integer_range#)*)?}', 'integer_list': '#integer_range#(?,#integer_range#)*'}
    Expanding:  {'f': '#e#', 'a': 'correct', 'd': '#c#', 'g': '#f#', 'b': '#a#', 'c': '#b#', 'e': '#d#'}
    Result:  {'f': '(((((correct)))))', 'a': 'correct', 'd': '(((correct)))', 'g': '((((((correct))))))', 'b': '(correct)', 'c': '((correct))', 'e': '((((correct))))'}
    

How could I update my code to achieve my goal?


Answer: Your problem is caused by the fact that python dictionaries are unordered. Try
using a
[OrderedDict](https://docs.python.org/2/library/collections.html#collections.OrderedDict)
instead of `dict` and you should be fine. The OrderedDict works just like a
normal `dict` but with ordering retained, at a small performance cost.

Note that while you could create an OrderedDict from a dict literal (like I
did here at first), that dict would be unordered, so the ordering might not be
guaranteed. Using a list of `(key, value)` pairs preserves the ordering in all
cases.

    
    
    from collections import OrderedDict
    
    test1=OrderedDict([('integer_set', '{#integer_list#?}'), ('integer_list', '#integer_range#(?,#integer_range#)*'), ('integer_range', '#integer#(..#integer#)?'), ('integer', '[+-]?\\d+')])
    test2=OrderedDict([('b', '#a#'), ('f', '#e#'), ('c', '#b#'), ('e', '#d#'), ('d', '#c#'), ('g', '#f#'), ('a', 'correct')])
    def change(pat_dict:{str:str}):
        print('Expanding: ',pat_dict)
        num=0
        while num<len(pat_dict):
            inv_pat_dict = {v: k for k, v in pat_dict.items()}
            for value in pat_dict.values():
                for key in pat_dict.keys():
                    if key in value:
                        repl='#'+key+'#'
                        repl2='('+pat_dict[key]+')'
                        value0=value.replace(repl,repl2)
                        pat_dict[inv_pat_dict[value]]=value0
            num+=1
        print('Result: ',pat_dict)
    
    change(test1)
    change(test2)
    

