如何在python的词典中进行替换?

时间:2016-10-14 04:30:44

标签: python dictionary

我想要实现的目标是将表单为#item_name#的所有项目与dict中的(item_value)进行交换。我使用两个dict test1test2来测试我的功能。这是代码:

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)

有时我可以得到正确的结果,如:

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'}

但是大部分时间我都会得到错误的结果:

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))))'}

如何更新我的代码以实现我的目标?

2 个答案:

答案 0 :(得分:0)

你的问题是因为python词典是无序的。尝试使用OrderedDict代替dict,您应该没问题。 OrderedDict的工作原理与普通dict一样,但保留了订单,但性能成本很低。

请注意,虽然您可以从dict文字创建一个OrderedDict(就像我最初在这里做的那样),但该dict将是无序的,因此可能无法保证排序。使用(key, value)对列表可以保留所有情况下的排序。

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)

答案 1 :(得分:0)

试试这个。你的问题是由于改变起始dict。你需要改变它的副本。

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(d):
    new_d = d.copy()
    for k in d.keys():
        for nk, v in new_d.items():
            if k in v:
                new_d[nk] = v.replace('#{}#'.format(k), '({})'.format(new_d[k]))
    return new_d

test1 = change(test1)
test2 = change(test2)