사전을 병합하는 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같은 일이다 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]. 질문은 사물을 결합하는 규칙을 명확하게 설명하지 않으므로 정확할 수 있습니다. 함수의 목적과 값 병합 규칙을 설명하는 주석 또는 문서 문자열이 도움이 될 것입니다.