sözlükleri birleştirmek için python3 işlevi

Aug 28 2020

Bir sürü JSON kaydım var, her kayıt farklı derecede eksiksizlik gösteriyor. Diğer bir deyişle, A kaydı B kaydında olmayan anahtarlar içerebilir ve bunun tersi de geçerlidir. İçindeki verileri daha iyi anlamak için, N sayıda kaydı alıp bunları bir araya getiren bir işlev oluşturdum, tüm anahtarları ve her anahtar için tek bir değeri içeren tek bir frankenstein kaydı oluşturdum.

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))

Bu, kodun çıktısıdır:

{
    "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"
    ]
}

İşlevi test ettim ve çalışıyor. İstediğim şey kodla ilgili bazı geri bildirimler. Bunu mümkün olan en verimli şekilde mi yapıyorum? Bunu yapmanın daha iyi yolları var mı?

Yanıtlar

5 RootTwo Aug 31 2020 at 12:16

keyParametresi için frankenstein()her yerde kullanılabilir görünmüyor ve elimine edilebilir.

Kodu daha küçük mantıksal parçalara bölmek için boş satırlar kullanın. Kodu okumaya ve anlamaya yardımcı olur.

in_dict yanıltıcı bir isimdir, çünkü bir liste, dikte veya tamamen başka bir şey olabilir.

Olarak for k, v in in_dict.items():döngü, in_dict[k]ve v, aynı şey v3 kez test edilir ve dönüş değeri setdefault()daha sonra bir sonraki satırda aranır atılır. Şu şekilde yeniden yazılabilir:

    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İşlemenin mantığı karmaşık görünüyor. Örneğin s, döngü boyunca her seferinde güncellenebilir ve ayrıca eklenebilir gibi görünüyor out[k]. Soru, bir şeyleri birleştirmenin kurallarını açıkça belirtmiyor, bu yüzden belki doğrudur. Fonksiyonun amacını ve değerleri birleştirme kurallarını açıklayan bir yorum veya belge dizgisi yardımcı olacaktır.