ฟังก์ชัน python3 เพื่อรวมพจนานุกรม
ฉันมีระเบียน 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"
]
}
ฉันได้ทดสอบฟังก์ชันแล้วและใช้งานได้ สิ่งที่ฉันต้องการคือความคิดเห็นเกี่ยวกับรหัส ฉันกำลังทำสิ่งนี้อย่างมีประสิทธิภาพที่สุดหรือไม่ มีวิธีที่ดีกว่านี้ไหม
คำตอบ
keyพารามิเตอร์frankenstein()ไม่ปรากฏที่จะใช้ที่ใดก็ได้และสามารถตัดออก
ใช้บรรทัดว่างเพื่อแบ่งโค้ดออกเป็นชิ้นส่วนตรรกะที่เล็กลง ช่วยในการอ่านและทำความเข้าใจรหัส
in_dict เป็นชื่อที่ทำให้เข้าใจผิดเพราะอาจเป็นรายการเขียนตามคำบอกหรืออย่างอื่นก็ได้
ในfor k, v in in_dict.items():ลูปin_dict[k]และvเป็นสิ่งเดียวกันvจะถูกทดสอบ 3 ครั้งและค่าส่งคืนของ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]ด้วย คำถามไม่ได้ระบุกฎสำหรับการรวมสิ่งต่างๆอย่างชัดเจนดังนั้นอาจจะถูกต้อง ข้อคิดเห็นหรือสตริงเอกสารที่อธิบายวัตถุประสงค์ของฟังก์ชันและกฎสำหรับการรวมค่าจะเป็นประโยชน์