辞書のリスト内の同じキーに新しい値を追加するには?

アイラ:

下に示したように、私はテスト失敗のリストを持っています -

all_failures = [
            'test1/path/to/test1/log/failure_reason1',
            'test1/path/to/test1/log/failure_reason2',
            'test2/path/to/test2/log/failure_reason1',
            'test2/path/to/test2/log/failure_reason2',
            'test3/path/to/test3/log/failure_reason1',
            'test4/path/to/test4/log/failure_reason1',
        ]

私は、リスト内の各故障を解析することにより、オブジェクトのようなJSONを構築しようとしています。これまでのところ、私は次のコードを記述しようとしました -

for failure in all_failures:
    data = failure.split('/',1)
    test = data[0]
    failure_details_dict[test] = []

    data = '/' + data[1]
    data = data.rsplit('/', 1)

    test_details_dict['path'] = data[0] + '/'
    test_details_dict['reason'] = data[1]

    failure_details_dict[test].append(test_details_dict)

    test_details_dict = {}  

for key,value in failure_details_dict.items():
    print(key)
    print(value)
    print()

私は取得しています出力されます -

test4
[{'reason': 'failure_reason1', 'path': '/path/to/test4/log/'}]

test3
[{'reason': 'failure_reason1', 'path': '/path/to/test3/log/'}]

test1
[{'reason': 'failure_reason2', 'path': '/path/to/test1/log/'}]

test2
[{'reason': 'failure_reason2', 'path': '/path/to/test2/log/'}]

一方、期待される出力があります-

{
    "test1": [
                {
                    "path": "/path/to/test1/log/",
                    "reason": "failure_reason1" 
                },
                {
                    "path": "/path/to/test1/log/",
                    "reason": "failure_reason2"     
                }

            ],
    "test2": [
                {
                    "path": "/path/to/test2/log/",
                    "reason": "failure_reason1" 
                },
                {
                    "path": "/path/to/test2/log/",
                    "reason": "failure_reason2"     
                }
            ],
    "test3": [
                {
                    "path": "/path/to/test3/log/",
                    "reason": "failure_reason1" 
                },
            ],
    "test4": [
                {
                    "path": "/path/to/test4/log/",
                    "reason": "reason1" 
                },
            ]
}

私たちが見ることができるように、私は追加することができていない第二 のパス失敗の理由を同じキーに。例- TEST1とTEST2は、障害のための2つの理由があります。

誰かが私が行方不明ですかを理解するための助けを喜ばせることはできますか?ありがとうございました!

宝城チェ:

理由

あなたはに上書きされているfailure_details_dict[test]全ての各ループのために。


解決

あなたは一度だけにリストを設定する必要があります。
あなたはそれを行うには、いくつかのオプションがあります。

  • 非ニシキヘビの方法(推奨しません
if test not in failure_details_dict:
    failure_details_dict[test] = []
  • 割り当てを交換dict.setdefaultコール。このようにして他の相互作用に影響を与えることはありません。failure_details_dict
failure_details_dict.setdefault(test, [])  # instead of failure_details_dict[test] = []
  • 使用collections.defaultdict代わりにdictこのようになりますAFFECTとの他の相互作用をfailure_detilas_dict
from collections import defaultdict

failure_details_dict = defaultdict(list)  # instead of {}

そして、私はあなたのコードをリファクタリングしています:

all_failures = [
    'test1/path/to/test1/log/failure_reason1',
    'test1/path/to/test1/log/failure_reason2',
    'test2/path/to/test2/log/failure_reason1',
    'test2/path/to/test2/log/failure_reason2',
    'test3/path/to/test3/log/failure_reason1',
    'test4/path/to/test4/log/failure_reason1',
]

failure_details_dict = {}

for failure in all_failures:
    key, *paths, reason = failure.split('/')
    failure_details_dict.setdefault(key, []).append({
        'path': f"/{'/'.join(paths)}/",
        'reason': reason,
    })

for key, value in failure_details_dict.items():
    print(key)
    print(value)
    print()

結論

  • あなたは簡単な変更をしたい場合は、使用dict.setdefault方法を。
  • あなたはへの複数のアクセスを持っている場合failure_details_dict、あなたはそれぞれのアクセス、利用のためのデフォルト値たいcollection.defaultdictクラスを。

エクストラ

その「パス」キーは一度だけコピーされ、「理由」キーを持つ唯一の複数の辞書が作成されるので、どのようにコードを変更することができますか?一般的に、何がJSON形式のデータを格納するための最良の方法だろうか?

あなたのJSONなどを再フォーマットすることができます:

{
  "test1": {
    "path": "/path/to/test1/log/",
    "reason": [
      "failure_reason1",
      "failure_reason2"
    ]
  },
  "test2": {
    "path": "/path/to/test2/log/",
    "reason": [
      "failure_reason1",
      "failure_reason2"
    ]
  },
  "test3": {
    "path": "/path/to/test3/log/",
    "reason": [
      "failure_reason1"
    ]
  },
  "test4": {
    "path": "/path/to/test4/log/",
    "reason": [
      "reason1"
    ]
  }
}

コードから:

all_failures = [
    'test1/path/to/test1/log/failure_reason1',
    'test1/path/to/test1/log/failure_reason2',
    'test2/path/to/test2/log/failure_reason1',
    'test2/path/to/test2/log/failure_reason2',
    'test3/path/to/test3/log/failure_reason1',
    'test4/path/to/test4/log/failure_reason1',
]

failure_details_dict = {}

for failure in all_failures:
    key, *paths, reason = failure.split('/')
    failure_details_dict.setdefault(key, {
        'path': f"/{'/'.join(paths)}/",
        'reason': [],
    })['reason'].append(reason)

for key, value in failure_details_dict.items():
    print(key)
    print(value)
    print()

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=28362&siteId=1