ฟังก์ชัน 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

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]ด้วย คำถามไม่ได้ระบุกฎสำหรับการรวมสิ่งต่างๆอย่างชัดเจนดังนั้นอาจจะถูกต้อง ข้อคิดเห็นหรือสตริงเอกสารที่อธิบายวัตถุประสงค์ของฟังก์ชันและกฎสำหรับการรวมค่าจะเป็นประโยชน์