辞書をマージするpython3関数
Aug 28 2020
私はたくさんのJSONレコードを持っており、各レコードの完全性はさまざまです。つまり、レコードAにはレコードBにないキーが含まれている場合があり、その逆の場合もあります。内部のデータをよりよく理解するために、N個のレコードを取得してそれらをマージする関数を作成し、すべてのキーと各キーの単一の値を含む単一のフランケンシュタインレコードを作成しました。
import sys
import json
def frankenstein(out, in_dict, key=None):
if isinstance(in_dict, dict):
for k, v in in_dict.items():
if isinstance(in_dict[k], list) and v:
out.setdefault(k, [])
frankenstein(out[k], v, k)
elif isinstance(in_dict[k], dict) and v:
out.setdefault(k, {})
frankenstein(out[k], v, k)
elif v:
out[k] = v
elif isinstance(in_dict, list):
s = {}
for item in in_dict:
if isinstance(item, dict):
frankenstein(s, item)
elif not out:
out.append(item)
if s:
if not out:
out.append(s)
else:
frankenstein(s, out[0])
out[0] = s
if __name__ == '__main__':
l = [
{
"name": "foo bar",
"experience": [
{
"company": {
"name": "oracle",
"hq": "123 main st",
"size": 100
},
"function": [
{
"name": "go getter"
}
],
"location": {
"doubleday": "publisher"
},
"animal": "horse"
}
],
"skills": ["programming", "eating"]
},
{
"name": "poo dar",
"experience": [
{
"company": {
"name": "microsoft",
"url": "foo.bar/com"
},
"function": [
{
"name": "bread",
"level": "really high"
}
],
"solitary": {
"fat": "cat"
},
"health": "no good"
}
],
"skills": ["igz"]
},
{
"name": "poo mar",
"experience": [
{
"function": [
{
"zoo": "creature"
}
],
"location": {
"taste": "food"
},
"ping": {
"pong": "bong"
}
}
],
"skills": ["woots own"]
}
]
out = {}
for item in l:
frankenstein(out, item)
print(json.dumps(out, indent=4))
これはコードからの出力です:
{
"name": "poo mar",
"experience": [
{
"function": [
{
"name": "bread",
"level": "really high",
"zoo": "creature"
}
],
"location": {
"taste": "food",
"doubleday": "publisher"
},
"ping": {
"pong": "bong"
},
"company": {
"name": "oracle",
"url": "foo.bar/com",
"hq": "123 main st",
"size": 100
},
"solitary": {
"fat": "cat"
},
"health": "no good",
"animal": "horse"
}
],
"skills": [
"programming"
]
}
私は機能をテストしました、そしてそれは働きます。私が欲しいのは、コードに関するいくつかのフィードバックです。私はこれを可能な限り最も効率的な方法で行っていますか?それを行うためのより良い方法はありますか?
回答
5 RootTwo Aug 31 2020 at 12:16
keytoのパラメーターfrankenstein()はどこでも使用されていないようであり、削除できます。
空白行を使用して、コードをより小さな論理チャンクに分割します。コードを読んで理解するのに役立ちます。
in_dict は誤解を招く名前です。これは、リスト、dict、またはその他のものである可能性があるためです。
でfor k, v in in_dict.items():ループ、in_dict[k]およびv同じものです、v3回試験され、かつの戻り値はsetdefault()次の行に見上げた後、破棄されます。次のように書き直すことができます。
for k, v in in_dict.items():
if not v:
continue
if isinstance(v, (list, dict)):
out_k = out.setdefault(k, v.__class__())
frankenstein(out_k, v)
else:
out[k] = v
処理のロジックlistsは複雑に見えます。たとえばs、ループを介して毎回更新され、に追加されるように見えout[k]ます。質問は物事を組み合わせるためのルールを明確に述べていないので、おそらくそれは正しいでしょう。関数の目的と値をマージするためのルールを説明するコメントまたはドキュメント文字列が役立ちます。