从字典的嵌套列表中删除特定键

时间:2020-05-15 13:25:15

标签: python recursion

我具有包含复杂字典的列表的特定格式,并且又包含字典列表(嵌套格式),例如

并且要求从所有关联词典中删除question_id

options = [
    {
        "value": 1,
        "label": "Paints",
        "question_id": "207",
        "question": "Which Paint Brand?",
        "question_type_id": 2,
        "options": [
            {
                "value": 2,
                "label": "Glidden",
                "question": "Is it Glidden Paint?",
                "question_id": 1,
                "options": [{"question_id": 1,"value": 10000, "label": "No"}, {"question_id": 1,"value": 10001, "label": "Yes"}],
            },
            {
                "value": 1,
                "label": "Valspar",
                "question": "Is it Valspar Paint?",
                "question_id": 1,
                "options": [{"question_id": 1,"value": 10000, "label": "No"}, {"question_id": 1,"value": 10001, "label": "Yes"}],
            },
            {
                "value": 3,
                "label": "DuPont",
                "question": "Is it DuPont Paint?",
                "question_id": 1,
                "options": [{"question_id": 1,"value": 10000, "label": "No"}, {"question_id": 1,"value": 10001, "label": "Yes"}],
            },
        ],
    },
    {
        "value": 4,
        "label": "Rods",
        "question": "Which Rods Brand?",
        "question_id": 2,
        "options": [
            {"value": 3, "label": "Trabucco"},
            {"value": 5, "label": "Yuki"},
            {"value": 1, "label": "Shimano"},
            {"value": 4, "label": "Daiwa"},
            {"value": 2, "label": "Temple Reef"},
        ],
    },
    {
        "value": 3,
        "label": "Metal Sheets",
        "question": "Which Metal Sheets Brand?",
        "question_id": 2,
        "options": [
            {"value": 2, "label": "Nippon Steel Sumitomo Metal Corporation"},
            {"value": 3, "label": "Hebei Iron and Steel Group"},
            {"value": 1, "label": "ArcelorMittal"},
        ],
    },
    {
        "value": 2,
        "label": "Door Knobs Locks",
        "question": "Which Door Knobs Locks Brand?",
        "question_id": 2,
        "options": [
            {
                "value": 1,
                "label": "ASSA-Abloy",
                "question": "Is it ASSA-Abloy Door Knobs Locks?",
                "question_type_id": 1,
                "options": [{"value": 10000, "label": "No"}, {"value": 10001, "label": "Yes"}],
            },
            {
                "value": 4,
                "label": "RR Brink",
                "question": "Is it RR Brink Door Knobs Locks?",
                "question_type_id": 1,
                "options": [{"value": 10000, "label": "No"}, {"value": 10001, "label": "Yes"}],
            },
            {
                "value": 3,
                "label": "Medeco",
                "question": "Is it Medeco Door Knobs Locks?",
                "question_type_id": 1,
                "options": [{"value": 10000, "label": "No"}, {"value": 10001, "label": "Yes"}],
            },
            {
                "value": 2,
                "label": "Evva",
                "question": "Is it Evva Door Knobs Locks?",
                "question_type_id": 1,
                "options": [{"value": 10000, "label": "No"}, {"value": 10001, "label": "Yes"}],
            },
        ],
    },
]

为此,我编写了一个代码并尝试递归运行它。

from collections import MutableMapping


def delete_keys_from_dict(dictionary_list, keys):
    keys_set = set(keys)  # Just an optimization for the "if key in keys" lookup.
    # modified_list=[]
    for index, dictionary in enumerate(dictionary_list):
        modified_dict = {}
        for key, value in dictionary.items():
            if key not in keys_set:
                if isinstance(value, list):
                    modified_dict[key] = delete_keys_from_dict(value, keys_set)
                else:
                    if isinstance(value, MutableMapping):
                        modified_dict[key] = delete_keys_from_dict(value, keys_set)
                    else:
                        modified_dict[key] = value
                        # or copy.deepcopy(value) if a copy is desired for non-dicts.
        dictionary_list[index] = modified_dict
    return dictionary_list

返回的列表不正确,并且不保留现有的列表数据。

我可以知道,我在哪里出错或在某处缺少什么东西?

1 个答案:

答案 0 :(得分:2)

我认为这样的事情应该可以满足您的要求。

obj可以是任何对象,并且可以递归到列表和字典中。

def delete_keys(obj, keys):
    if isinstance(obj, list):
        return [
            delete_keys(item, keys)
            for item in obj
        ]
    if isinstance(obj, dict):
        return {
            key: delete_keys(value, keys)
            for (key, value) in obj.items()
            if key not in keys
        }
    return obj  # Nothing to do for this value

例如

from pprint import pprint

options = [
    {
        "value": 1,
        "label": "Paints",
        "question_id": "207",
        "question": "Which Paint Brand?",
        "question_type_id": 2,
        "options": [
            {
                "value": 2,
                "label": "Glidden",
                "question": "Is it Glidden Paint?",
                "question_id": 1,
                "options": [{"question_id": 1,"value": 10000, "label": "No"}, {"question_id": 1,"value": 10001, "label": "Yes"}],
            }
        ],
    },
    {
        "value": 4,
        "label": "Rods",
        "question": "Which Rods Brand?",
        "question_id": 2,
        "options": [
            {"value": 3, "label": "Trabucco"},
            {"value": 5, "label": "Yuki"},
            {"value": 1, "label": "Shimano"},
            {"value": 4, "label": "Daiwa"},
            {"value": 2, "label": "Temple Reef"},
        ],
    },
]

pprint(delete_keys(options, {"question_id"}))

输出

[{'label': 'Paints',
  'options': [{'label': 'Glidden',
               'options': [{'label': 'No', 'value': 10000},
                           {'label': 'Yes', 'value': 10001}],
               'question': 'Is it Glidden Paint?',
               'value': 2}],
  'question': 'Which Paint Brand?',
  'question_type_id': 2,
  'value': 1},
 {'label': 'Rods',
  'options': [{'label': 'Trabucco', 'value': 3},
              {'label': 'Yuki', 'value': 5},
              {'label': 'Shimano', 'value': 1},
              {'label': 'Daiwa', 'value': 4},
              {'label': 'Temple Reef', 'value': 2}],
  'question': 'Which Rods Brand?',
  'value': 4}]