簡體   English   中英

如何將列表的嵌套字典(帶有字典)轉換為單個字典列表?

[英]How do I turn a nested dict of lists (with dicts) into a single list of dicts?

我想將一個非常復雜的字典轉換為一個帶有字典的列表(如 SQL 連接)。

輸入:

{
    'company': 'A',
    'employee': [
        {'name': 'John', 'skills': ['python', 'java']},
        {'name': 'Mary', 'skills': ['web', 'databases']}
    ]
}

Output:

[
    {'company': 'A', 'employee': {'name': 'John', 'skills': 'python'}},
    {'company': 'A', 'employee': {'name': 'John', 'skills': 'java'}},
    {'company': 'A', 'employee': {'name': 'Mary', 'skills': 'web'}},
    {'company': 'A', 'employee': {'name': 'Mary', 'skills': 'databases'}},
]

我希望能夠添加更多嵌套列表以及添加更多公司等......所以硬編碼字典和列表的級別不是一種選擇。 遞歸似乎是我唯一的選擇。

有沒有人有任何指示如何 go 這樣做?

對於第一級,我想出了這個,但是當我開始遞歸調用 flatten function 時遇到了麻煩


def flatten(input):
    output = []
    for item in input:
        if isinstance(input[item], list):
            for subitem in input[item]:
                copy = input
                # Doesnt work
                # copy[item] = flatten(subitem)

                # Only works for the first layer
                copy[item] = subitem
                output.append(copy.copy())
    return output
print(flatten(start))

此代碼適用於第一級(為每個員工添加新記錄),但遞歸調用 flatten 會使 output 返回一個空列表

假設輸入 dict 中始終只有一個值是一個列表,您可以先找到具有列表值的鍵,然后返回當前 dict 的列表,並將該鍵的值替換為遞歸展平的每個值,直到該值不再是一個字典:

def flatten(d):
    if isinstance(d, dict):
        key, lst = next((k, v) for k, v in d.items() if isinstance(v, list))
        return [{**d, **{key: v}} for record in lst for v in flatten(record)]
    else:
        return [d]

flatten(d)返回(給定樣本輸入 dict 為d ):

[{'company': 'A', 'employee': {'name': 'John', 'skills': 'python'}},
 {'company': 'A', 'employee': {'name': 'John', 'skills': 'java'}},
 {'company': 'A', 'employee': {'name': 'Mary', 'skills': 'web'}},
 {'company': 'A', 'employee': {'name': 'Mary', 'skills': 'databases'}}]

或者,如果 dict 中可能存在一個沒有列表值的級別,在這種情況下,使用上面的代碼調用next function 將產生一個StopIteration ,您可以捕獲該異常並返回輸入 dict就像在列表中一樣,並且由於當輸入不是字典時這是相同的行為,您可以簡單地捕獲AttributeError異常(當給定的 object 沒有items屬性時產生)也可以使用相同的處理程序代碼處理這兩種情況:

def flatten(d):
    try:
        key, lst = next((k, v) for k, v in d.items() if isinstance(v, list))
    except (StopIteration, AttributeError):
        return [d]
    return [{**d, **{key: v}} for record in lst for v in flatten(record)]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM