2016-10-14 11 views
3

私が達成したい目標は、書式が#item_name#のすべてのアイテムを、dictの(item_value)に交換することです。私はtest1test2という2つのdictを使って私の機能をテストします。ここでは、コードは次のようになります。pythonの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(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))))'} 

どのように私は私を更新でき私の目標を達成するためのコード?

答えて

0

あなたの問題は、python辞書が順序付けられていないことが原因です。 dictの代わりにOrderedDictを使用してみてください。うまくいくはずです。 OrderedDictは通常のdictのように動作しますが、注文を保留してもパフォーマンスはわずかです。

dictリテラルからOrderedDictを作成することはできますが(私がここでやったのと同じように)、その辞書には順序がないため、順序が保証されない場合があります。 (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) 
+0

ランダムに[され、DOS EDからWebサービスを防止する]である(https://docs.python.org/3/reference/datamodel.html#object.__hash__)ユーザーが任意のキーを作成することができるとき'dict'の操作を' O(n) 'に減らして、ハッシュ衝突を引き起こすようにキーを工作するかもしれません。反復順序に影響するという事実は実際にはデザイン上の問題ではありません(そして、実際にCPython 3.6では 'dict'は実装の変更によってデフォルトで挿入順で反復される可能性があります。空想的な「dict」デザインへの変更の効果)。 – ShadowRanger

+0

私は訂正しました。同じ動作がGoにあります。ここでは、開発者が 'map'出力の順序を信用するのを避けるためです。編集されました。私が得られないのは、断続的な書き込みを行わずに各読み取りで繰り返し順序が変わる理由です。どのようにこれはハッシュの衝突を避けるでしょうか? @ShadowRanger –

0

これを試してみてください。あなたの問題は、始まりの言葉を変えることによるものです。そのコピーを変更する必要があります。

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) 
関連する問題