bugfix> python > 投稿

リスト内の辞書を反復処理するのに問題があります。

次のようなリストがあります。

mylist[0]
{'_id': ObjectId('aleatoryID'),
 'created_at': datetime.datetime(2018, 3, 22, 11, 58, 23, 585000),
 'person': {'id': '00115500',
  'scores': {'SCORE_3': {'@score': '45'}, 'SCORE_1': 205, 'SCORE_2': 487}}}

SCORE_1とSCORE_2を繰り返し処理しても問題はありません。サブ構造が含まれているため、私の問題はSCORE_3です。 私の試みは次のとおりです。

persons = []
for document in mylist:
    persons.append((document['person'].get('id'),
                    document['created_at'],
                    document['person']['scores'].get('SCORE_1'),
                    document['person']['scores'].get('SCORE_2'),
                    document['person']['scores']['SCORE_3'].get('@score')
                   ))
KeyError: 'SCORE_3'

この状況で辞書を繰り返す正しい方法は何ですか?

回答 2 件
  • サブディクショナリに存在しないエントリがいくつかあります。これを処理する方法にはいくつかのアプローチがあり、ニーズに最も適したものを選択してください。

    # base case
    for document in mylist:
        persons.append((document['person'].get('id'),
                        document['created_at'],
                        document['person']['scores'].get('SCORE_1'),
                        document['person']['scores'].get('SCORE_2'),
                        # the line below causes the trouble
                        document['person']['scores']['SCORE_3'].get('@score') 
                       ))
    
    

    #1デフォルト値を含める

    # a tad more tricky than just calling `get`, since you want to work with the
    # potential result. Substitute the `None` with the default value of your choice
    ... document['person']['scores'].get('SCORE_3', {}).get('@score', None)
    
    

    #2そのような場合はスキップする

    try:
        persons.append((document['person'].get('id'),
                        document['created_at'],
                        document['person']['scores']['SCORE_1'],
                        document['person']['scores']['SCORE_2'],
                        document['person']['scores']['SCORE_3']['@score'])
                       ))
    except KeyError:
        pass
    
    

    #3ケースをスキップせず、フィールドのみ

    # couldn't find a way that didn't include 5 `try...except`s or doing approach #1 
    # and then filtering `None`s with [x for x in #1 if x is not None]. So I guess 
    # default values > skipping fields.
    
    

  • あなたの例に基づいて、これはうまくいくはずです:

    document['person']['scores'].get('SCORE_3')['@score']
    
    

    または、 get を使用せずにインデックスを作成する :

    document['person']['scores']['SCORE_3']['@score']
    
    

あなたの答え