【Py】列表字典转为字典

假设我们有如下列表

[
  {
    "一级": "数码产品",
    "二级": "手机",
    "三级": "苹果",
    "四级": "iPhone11",
    "编码": "001"
  },
  {
    "一级": "数码产品",
    "二级": "电脑",
    "三级": "苹果",
    "四级": "MacBook",
    "编码": "002"
  },
  {
    "一级": "数码产品",
    "二级": "手机",
    "三级": "苹果",
    "四级": "iPhone12",
  	"编码": "003"
  },
  {
    "一级": "数码产品",
    "二级": "耳机",
    "三级": "苹果",
    "四级": "AirPods",
    "编码": "004"
  },
  {
    "一级": "数码产品",
    "二级": "手机",
    "三级": "三星",
    "四级": "Galaxy",
    "编码": "005"
  }
]

我们希望将其变为如下树形结构的字典

{
  "数码产品": {
    "手机": {
      "苹果": {
        "iPhone11": {
          "编码": "001"
        },
        "iPhone12": {
          "编码": "003"
        }
      },
      "三星": {
        "Galaxy": {
          "编码": "005"
        }
      }
    },
    "电脑": {
      "苹果": {
        "MacBook": {
          "编码": "002"
        }
      }
    },
    "耳机": {
      "苹果": {
        "AirPods": {
          "编码": "004"
        }
      }
    }
  }
}
test = [
    {"一级": "数码产品", "二级": "手机", "三级": "苹果", "四级": "iPhone", "编码": "001"},
    {"一级": "数码产品", "二级": "电脑", "三级": "苹果", "四级": "MacBook", "编码": "002"},
    {"一级": "数码产品", "二级": "耳机", "三级": "苹果", "四级": "AirPods", "编码": "003"},
    {"一级": "数码产品", "二级": "手机", "三级": "三星", "四级": "Galaxy", "编码": "004"}
]

for name_0 in set(d['一级'] for d in test):
    dic[name_0] = {}
    for name_1 in set(d['二级'] for d in test if d['一级'] == name_0):
        dic[name_0][name_1] = {}
        for name_2 in set(d['三级'] for d in test if d['一级'] == name_0 and d['二级'] == name_1):
            dic[name_0][name_1][name_2] = {}
            for name_3 in set(d['四级'] for d in test if d['一级'] == name_0 and d['二级'] == name_1 and d['三级'] == name_2):
                dic[name_0][name_1][name_2][name_3] = {}

for item in test:
   dic[item['一级']][item['二级']][item['三级']][item['四级']]['编码'] = item['编码']

但是这种方式单从代码上看就非常繁琐,而且不灵活,应该还会有更好的办法

我们发现以下代码仅是为了创建分支节点

for name_0 in set(d['一级'] for d in test):
    dic[name_0] = {}
    for name_1 in set(d['二级'] for d in test if d['一级'] == name_0):
        dic[name_0][name_1] = {}
        for name_2 in set(d['三级'] for d in test if d['一级'] == name_0 and d['二级'] == name_1):
            dic[name_0][name_1][name_2] = {}
            for name_3 in set(d['四级'] for d in test if d['一级'] == name_0 and d['二级'] == name_1 and d['三级'] == name_2):
                dic[name_0][name_1][name_2][name_3] = {}

我们可以利用defaultdict,在键不存在的时候自动创建,从而将上面的代码省略掉

import json
from collections import defaultdict

test = [
    {"一级": "数码产品", "二级": "手机", "三级": "苹果", "四级": "iPhone", "编码": "001"},
    {"一级": "数码产品", "二级": "电脑", "三级": "苹果", "四级": "MacBook", "编码": "002"},
    {"一级": "数码产品", "二级": "耳机", "三级": "苹果", "四级": "AirPods", "编码": "003"},
    {"一级": "数码产品", "二级": "手机", "三级": "三星", "四级": "Galaxy", "编码": "004"}
]
dic = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(dict))))
for item in test:
    dic[item['一级']][item['二级']][item['三级']][item['四级']]['编码'] = item['编码']

# 转为字典
json.loads(json.dumps(dic))

注意:

  1. 转字典时,dict()方式仅能转换根节点,子节点则依然为defaultdict,故需要使用json;
  2. 上面定义的dic最大能满足层数为5的树,如果层数大于5则需要在定义dic的时候再多嵌套若干层defaultdict(lambda: defaultdict(dict))

参考:
https://howchoo.com/python/nested-defaultdict-python
https://stackoverflow.com/a/32303615/7151777

<think>好的,我现在需要帮用户解决如何用Python将Excel文件换为JSON的问题。用户提到了使用pandas或openpyxl库,所以我得先回顾一下这两个库的相关知识。 首先,pandas是一个强大的数据处理库,可以方便地读取Excel文件并换为DataFrame,然后再导出为JSON。根据引用[2]和[3],pandas的read_excel函数可以读取Excel,并且结合to_dict方法能换成字典,这可能对生成JSON有帮助。同时,引用[5]也提到pandas处理学生成绩Excel的案例,说明它在处理Excel数据方面是可靠的。 然后是openpyxl,引用[1]说明它是专门操作Excel文件的库,适合读取单元格数据。虽然pandas更高效,但如果需要更细致的控制,比如处理特定格式或单元格,openpyxl可能更合适。不过用户的需求是换为JSON,可能更倾向于pandas的便捷性。 接下来,我需要考虑具体的实现步骤。使用pandas的话,大致步骤是读取Excel文件,处理数据,然后换为JSON。需要注意参数比如orient,可能用户需要不同的JSON结构,比如records或者index。引用[3]提到使用to_dict(orient='records'),这可能生成列表形式的JSON,每个元素是一条记录,这可能符合常见需求。 另外,用户可能需要处理不同的sheet,或者特定区域的数据。比如,是否需要读取所有sheet,或者指定某个sheet名。pandas的read_excel可以指定sheet_name参数,而openpyxl则需要遍历workbook的sheets。 还需要注意Excel文件的格式,比如xlsx或xlsm。根据引用[1],openpyxl支持这些格式,而pandas在读取时可能需要指定engine='openpyxl',特别是对于xlsm文件,如引用[2]中的例子。 然后,关于JSON的格式化,可能需要处理日期等特殊类型,确保换正确。此外,是否保留索引,或者是否需要嵌套结构,这些都需要在代码中调整参数。 可能的进阶需求包括处理多个sheet、合并数据、或者自定义键名。比如,用户可能需要每个sheet生成一个JSON文件,或者将多个sheet的数据整合到一个JSON中。这时候需要更复杂的逻辑,比如遍历sheets,或者使用字典嵌套。 测试案例方面,可以提供一个简单的示例,比如读取一个sheet,换为records格式的JSON。然后再展示如何处理多个sheet的情况。代码示例需要确保正确性,比如使用pandas的read_excel和to_json方法,或者用openpyxl逐行读取数据构建字典列表。 最后,生成相关问题时,需要考虑用户可能进一步的需求,比如处理大型Excel的性能优化、处理特定格式的单元格(如日期、公式),或者如何保持数据类型的一致性。另外,错误处理也是需要注意的,比如文件不存在或格式错误时的异常捕获。</think>### 使用Python将Excel换为JSON的步骤 #### 方法1:使用pandas(适用于结构化数据处理) 1. **安装依赖库** 需安装`pandas`和`openpyxl`(用于处理Excel文件): ```bash pip install pandas openpyxl ``` 2. **读取Excel文件** 使用`pd.read_excel`加载Excel数据为DataFrame: ```python import pandas as pd df = pd.read_excel("input.xlsx", engine="openpyxl") # 明确指定引擎[^2] ``` 3. **换为JSON** 将DataFrame换为JSON格式,并保存到文件: ```python # 换为列表形式的JSON(每条记录为一个字典) json_data = df.to_json(orient="records", indent=4, force_ascii=False) with open("output.json", "w", encoding="utf-8") as f: f.write(json_data) ``` - `orient="records"`:生成`[{"列1":"值1", ...}, ...]`格式的JSON[^3] - `force_ascii=False`:支持中文字符 --- #### 方法2:使用openpyxl(适用于精细控制单元格) 1. **安装openpyxl** ```bash pip install openpyxl ``` 2. **读取Excel并构建字典列表** 逐行读取数据并生成JSON结构: ```python from openpyxl import load_workbook import json wb = load_workbook("input.xlsx") sheet = wb.active headers = [cell.value for cell in sheet[1]] # 假设第一行为表头 data = [] for row in sheet.iter_rows(min_row=2): # 从第二行开始读取数据 row_data = {headers[i]: cell.value for i, cell in enumerate(row)} data.append(row_data) with open("output.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=4) ``` --- #### 进阶案例:处理多Sheet或复杂结构 若需将**每个Sheet保存为独立JSON文件**: ```python import pandas as pd with pd.ExcelFile("input.xlsx", engine="openpyxl") as xls: for sheet_name in xls.sheet_names: df = pd.read_excel(xls, sheet_name=sheet_name) df.to_json(f"{sheet_name}.json", orient="records", force_ascii=False) ``` --- ### 注意事项 1. **日期格式处理** Excel中的日期可能被换为时间戳,需手动格式化: ```python df["日期列"] = df["日期列"].dt.strftime("%Y-%m-%d") ``` 2. **空值处理** pandas默认将空值转为`null`,openpyxl可通过条件判断过滤`None`。 3. **性能优化** - 大型文件建议使用`chunksize`分块读取(pandas) - 避免在openpyxl中频繁操作单元格 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值