19

私はこのようなobjを持っています

{hello: 'world', "foo.0.bar": v1, "foo.0.name": v2, "foo.1.bar": v3}

に拡張する必要があります

{ hello: 'world', foo: [{'bar': v1, 'name': v2}, {bar: v3}]}

私は以下のコードを書き、分割し'.'、古いキーを削除し、含まれている場合は新しいキーを追加しますが'.'RuntimeError: dictionary changed size during iteration

def expand(obj):
    for k in obj.keys():
        expandField(obj, k, v)

def expandField(obj, f, v):
    parts = f.split('.')
    if(len(parts) == 1):
        return
    del obj[f]
    for i in xrange(0, len(parts) - 1):
        f = parts[i]
        currobj = obj.get(f)
        if (currobj == None):
            nextf = parts[i + 1]
            currobj = obj[f] = re.match(r'\d+', nextf) and [] or {}
        obj = currobj
    obj[len(parts) - 1] = v

obj.iteritems()のk、vの場合:

RuntimeError:反復中に辞書のサイズが変更されました

4

5 に答える 5

28

メッセージにあるように、expandでこのエントリをループしている最中に、expandField()内のobjのエントリ数を変更しました。

代わりに、希望する形式の新しい辞書を作成するか、何らかの方法で変更を記録して、ループが完了した後にそれらを作成してみてください。

于 2012-04-11T14:15:36.813 に答える
12

リスト内のキーをコピーし、後者を使用してdictを反復処理することをお勧めします。例:

def expand(obj):
    keys = obj.keys()
    for k in keys:
        expandField(obj, k, v)

結果の動作が期待される結果に適合するかどうかを分析します。

于 2014-02-11T22:07:49.477 に答える
3

他の辞書内で辞書の構造を変更(削除/追加)することについても同様の問題がありました。

私の状況では、口述のディープコピーを作成しました。私の口述のディープコピーを使用して、必要に応じてキーを繰り返し処理して削除することができました。ディープコピー-PythonDoc

ディープコピーは、新しい複合オブジェクトを作成し、その後、元のオブジェクトで見つかったオブジェクトのコピーを再帰的に挿入します。

お役に立てれば!

于 2013-09-14T21:24:47.173 に答える
0

この部分を書き直す

def expand(obj):
    for k in obj.keys():
        expandField(obj, k, v)

次へ

def expand(obj):
    keys = obj.keys()
    for k in keys:
        if k in obj:
            expandField(obj, k, v)

それを機能させるものとします。

于 2020-05-07T02:19:16.310 に答える
0

経験者のために

RuntimeError: dictionary changed size during iteration

また、存在しないキーにアクセスしようとするときに、を繰り返してdefaultdictいないことを確認してください。forループ内でそれを実行していることに気づきました。これにより、defaultdictがこのキーのデフォルト値を作成し、前述のエラーが発生しました。

解決策は、ループdefaultdictする前にに変換することです。dict

d = defaultdict(int)
d_new = dict(d)

または、キーを繰り返し処理している間、キーを追加/削除していないことを確認してください。

于 2020-06-14T13:35:12.593 に答える