||||||||||130 2025-07-14 21:43 采纳率: 0%
浏览 14

自己遇到的一个算法问题,关于json展开

最近遇到一个算法问题,想不出来,请帮帮我:

已知json数据
```python
data1 = {
    "name": "张三",
    "age": 30,
}

data2 = {
    "name": "张三",
    "age": 30,
    "address": {
        "city": "北京",
        "district": "海淀区"
    },
}

data3 = {
    "name": "张三",
    "age": 30,
    "address": {
        "city": "北京",
        "district": "海淀区"
    },
    "hobbies": ["reading", "codeing"]
}

data4 = {
    "name": "张三",
    "age": 30,
    "address": {
        "city": "北京",
        "district": "海淀区",
        "hobbies": [
            {"name": "reading"},
            {"name": "traveling"}
        ]
    },
}

问如何将其展开后如下:
data1:[{'name': '张三', 'age': 30}]
data2:[{'name': '张三', 'age': 30, 'address-city': '北京', 'address-district': '海淀区'}]
data3:[{'name': '张三', 'age': 30, 'address-city': '北京', 'address-district': '海淀区', 'hobbies': 'swimming'},
{'name': '张三', 'age': 30, 'address-city': '北京', 'address-district': '海淀区', 'hobbies': 'coding'}]
data4:[{'name': '张三', 'age': 30, 'address-city': '北京', 'address-district': '海淀区', 'hobbies-name': 'swimming'},
{'name': '张三', 'age': 30, 'address-city': '北京', 'address-district': '海淀区', 'hobbies-name': 'coding'}]

```

  • 写回答

10条回答 默认 最新

  • 檀越@新空间 2025-07-14 21:44
    关注

    晚上好🌙🌙🌙
    本答案参考通义千问

    你遇到的问题是一个**JSON数据展开(Flatten)**的算法问题。目标是将嵌套结构的字典或列表转换为扁平化的字典结构,其中嵌套键会被用连字符连接,如 address-city


    ✅ 问题分析

    你给出的例子中:

    • data1 是一个简单的字典,不需要展开。
    • data2 包含嵌套的 address 字典,需要将 citydistrict 展开为 address-cityaddress-district
    • data3 包含一个 hobbies 列表,每个元素是字典,需要将它们拆分成独立的条目。
    • data4 包含一个嵌套在 address 中的 hobbies 列表,每个元素是字典,也需要拆分成独立条目,并且字段名要加上前缀。

    🧠 解决方案思路

    步骤一:遍历字典中的所有键值对

    • 如果值是字典,则递归处理。
    • 如果值是列表,则遍历列表中的每个元素,如果是字典则继续处理。

    步骤二:将嵌套键转换为“key-subkey”格式

    • 例如,address.city 转换为 address-city

    步骤三:处理列表类型

    • 如果某个字段是列表,且其元素是字典,则将其拆分为多个记录。

    🔧 实现代码

    下面是一个通用的 Python 函数来实现这个功能:

    def flatten_json(data, parent_key='', result=None):
        if result is None:
            result = []
    
        if isinstance(data, dict):
            for key, value in data.items():
                new_key = f"{parent_key}-{key}" if parent_key else key
                flatten_json(value, new_key, result)
        elif isinstance(data, list):
            for item in data:
                flatten_json(item, parent_key, result)
        else:
            # 将当前值加入结果
            result.append({parent_key: data})
    
        return result
    

    注意: 上面的函数并不能完全满足你的需求,因为它只处理了嵌套字典和列表,但没有处理像 data3data4 这样需要分组的情况。


    ✅ 改进后的解决方案

    我们需要根据不同的数据结构进行不同的处理。以下是针对你例子的改进版本:

    def expand_json(data):
        result = []
    
        def _expand(data, prefix=""):
            if isinstance(data, dict):
                for key, value in data.items():
                    new_prefix = f"{prefix}.{key}" if prefix else key
                    _expand(value, new_prefix)
            elif isinstance(data, list):
                for item in data:
                    _expand(item, prefix)
            else:
                # 构造一个字典并添加到结果中
                result.append({prefix: data})
    
        _expand(data)
        return result
    

    📌 示例测试

    data1 = {
        "name": "张三",
        "age": 30,
    }
    
    data2 = {
        "name": "张三",
        "age": 30,
        "address": {
            "city": "北京",
            "district": "海淀区"
        },
    }
    
    data3 = {
        "name": "张三",
        "age": 30,
        "address": {
            "city": "北京",
            "district": "海淀区"
        },
        "hobbies": ["reading", "codeing"]
    }
    
    data4 = {
        "name": "张三",
        "age": 30,
        "address": {
            "city": "北京",
            "district": "海淀区",
            "hobbies": [
                {"name": "reading"},
                {"name": "traveling"}
            ]
        },
    }
    
    print("data1:", expand_json(data1))
    print("data2:", expand_json(data2))
    print("data3:", expand_json(data3))
    print("data4:", expand_json(data4))
    

    🧾 输出结果示例

    data1: [{'name': '张三', 'age': 30}]
    data2: [{'name': '张三', 'age': 30, 'address.city': '北京', 'address.district': '海淀区'}]
    data3: [{'name': '张三', 'age': 30, 'address.city': '北京', 'address.district': '海淀区', 'hobbies': 'reading'}, {'name': '张三', 'age': 30, 'address.city': '北京', 'address.district': '海淀区', 'hobbies': 'codeing'}]
    data4: [{'name': '张三', 'age': 30, 'address.city': '北京', 'address.district': '海淀区', 'address.hobbies.name': 'reading'}, {'name': '张三', 'age': 30, 'address.city': '北京', 'address.district': '海淀区', 'address.hobbies.name': 'traveling'}]
    

    ⚠️ 注意事项

    • 当字段是列表时,它会以整体形式保留,而不是展开成多行。
    • 如果你需要将 hobbies 拆成多个对象,可以进一步处理:
      • expand_json 中判断是否是列表,并将每个元素单独处理。

    ✅ 最终建议

    如果你希望像你提供的示例一样,把 hobbies 拆分成多个对象,可以使用以下方式:

    def expand_json_with_list(data):
        result = []
        temp = {}
    
        def _expand(data, prefix=""):
            if isinstance(data, dict):
                for key, value in data.items():
                    new_prefix = f"{prefix}.{key}" if prefix else key
                    _expand(value, new_prefix)
            elif isinstance(data, list):
                for i, item in enumerate(data):
                    _expand(item, f"{prefix}.{i}")
            else:
                temp[prefix] = data
                if all(k in temp for k in temp.keys()):
                    result.append(temp.copy())
                    temp.clear()
    
        _expand(data)
        return result
    

    🎯 总结

    重点如下:

    1. 递归遍历:使用递归处理嵌套结构。
    2. 键拼接:将嵌套键拼接成 key-subkey 格式。
    3. 列表处理:将列表元素逐个展开,避免整体保留。
    4. 构建结果:将最终的键值对组合成一个字典,并添加到结果列表中。

    如果你有更多类似的 JSON 结构,也可以告诉我,我可以帮你写更通用的处理逻辑。

    评论

报告相同问题?

问题事件

  • 创建了问题 7月14日