2017-06-05 14 views
1

JSONオブジェクトのすべての葉に対してイテレータが必要です。だから私はこの関数を書いた新しいイテレータ内でイテレータの要素を生成する方法は?

rec = {'a': {'b': [{'c': {'d': [{'e': 'x1','f': 'x2'}],'g': 'x3'}}],'h': 'x4','i': 'x5','j': [{'k': 'x6'}],'l': [{'m': {'n': 'x7'}}]}} 

def yield_leaves(rec, lbl = ''): 
    if isinstance(rec, dict): 
    for key, value in rec.items(): 
     for to_yield in yield_leaves(value, key): 
      yield to_yield 
    if isinstance(rec, list): 
    for value in rec: 
     for to_yield in yield_leaves(value, lbl): 
      yield to_yield 
    if isinstance(rec, (int, str)): 
    for entry in rec.split(): 
     yield entry, lbl 

print(list(yield_leaves(rec))) 
>>> [('x5', 'i'), ('x4', 'h'), ('x1', 'e'), ('x2', 'f'), ('x3', 'g'), ('x6', 'k'), ('x7', 'n')] 

しかし、私はいくつかのコードは冗長だと思う。次の行

for to_yield in yield_leaves(value, key): 
     yield to_yield 

それはイテレータを反復処理して、イテレータの一部として値を返します。

これをコードするより効率的な方法がわかりますか?

+2

Python 3のyield_leaves(value、key)からの降順 –

答えて

1

あなたの最後のセクションを使用している場合

if isinstance(rec, (int, str)): 
    for entry in rec.split(): 
     yield entry, lbl 

は少し奇妙です。整数には.splitメソッドがないため、recintの場合はクラッシュします。あなたの文字列には空白が含まれていないので、.splitを呼び出すと、元の文字列である単一の項目を含むリストが返されます。あなたの実際のデータには分割したい複数の単語の文字列が入っているかもしれませんが、もしそうなら、あなたは本当にそれを別々にintから扱う必要があります。

したがって、に分割したい複数の単語の値を持つがないと仮定して、コードを少し簡略化しました。ご覧のとおり、dictテストとlistテストのみを保持しています。データはJSONからデコードされているため、他のrecタイプは、int,str,boolまたはNoneのようなスカラーになります。カスタムデコード)、すべてのスカラー型を同じように扱うことができます。

rec = { 
    'a': { 
     'b': [ 
      { 
       'c': { 
        'd': [{'e': 'x1', 'f': 'x2'}], 
        'g': 'x3' 
       } 
      } 
     ], 
     'h': 'x4', 
     'i': 'x5', 
     'j': [{'k': 'x6'}], 
     'l': [{'m': {'n': 'x7'}}] 
    } 
} 

def yield_leaves(rec, lbl=''): 
    if isinstance(rec, dict): 
     for key, value in rec.items(): 
      yield from yield_leaves(value, key) 
    elif isinstance(rec, list): 
     for value in rec: 
      yield from yield_leaves(value, lbl) 
    else: 
     yield rec, lbl 

print(list(yield_leaves(rec))) 

出力

[('x1', 'e'), ('x2', 'f'), ('x3', 'g'), ('x4', 'h'), ('x5', 'i'), ('x6', 'k'), ('x7', 'n')] 

このコードは、Python 3機能yield fromを使用します。 Python 3を使用していない場合は、そうする必要があります。 :)

+0

はい、 '' 'from yield'''は私が探していたことをします。ありがとう。 –

+0

あなたは整数の分割を呼び出すことについて正しいです。私の側のコピー貼り付けが悪い –

+0

@RobRomijnders心配はいりません。私の答えがあなたを助けてくれたなら、それを[受け入れる](http://meta.stackexchange.com/a/5235)と考えてください。 –

1

のための代わりの利回りを使用してみてください
yeild from yield_leaves(value, key) 

P.S.あなたのpython> 3.3

+0

はい、 '' 'yield from'''がトリックです! –

関連する問題