You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效将JavaScript深度嵌套数组转换为可下载CSV?

深度嵌套数组转CSV的高效实现方案

问题描述

我有一个深度嵌套数组,需要将其转换为可下载的CSV文件。目前我正通过遍历每个数组及子数组来构建CSV,想请教是否存在更高效的实现方式?

嵌套数组示例

[{
    id: 123,
    name: "ABC",
    superDepartment: [{
        id: 456,
        name: "PQR",
        keyCompetitor: ["JKL"],
        department: [{
            id: 765,
            name: "XYZ",
            category: [{
                id: 965,
                name: "GHJ",
                keyCompetitor: ["NMK"],
                otherCompetitor: ["SDF", "LKJ"],
                subcategory: [
                    {id: 346, name: "DRJ"},
                    {id: 789, name: "SRE"}        
                ]
            }]
        }]
    }]
}];

预期CSV输出

SBUSuper DepartmentDepartmentCategorySubcategoryKey CompetitorCore CompetitorOther Competitor
ABC
PQRJKL
XYZ
GHJNMKSDF, LKJ
DRJ
SRE

当前实现代码

let csvData = [];
downloadData.map(data => {
    if(csvData.length === 0) {
        csvData.push(data.name, "", "", "", csvData.keyCompetitors ? csvData.keyCompetitors[0] : "",
        csvData.coreCompetitors ?  csvData.coreCompetitors.join(): "",
        csvData.otherCompetitors ? csvData.otherCompetitors.join() : "")
    }
});

高效实现思路与代码

你的当前实现仅处理了最外层数据,无法覆盖深层嵌套结构。更高效的方式是使用递归遍历,它能自动适配任意嵌套层级,同时维护当前行的上下文信息,确保每一行的列值正确对齐。

步骤1:递归遍历生成CSV行数据

定义递归函数,遍历每个节点并生成对应CSV行,传递当前上下文(已填充的列值),遇到子数组则继续递归处理。

// 定义CSV表头
const headers = ["SBU", "Super Department", "Department", "Category", "Subcategory", "Key Competitor", "Core Competitor", "Other Competitor"];

// 递归遍历嵌套数组,生成CSV行数据
function generateRows(data, currentRow = {}) {
    let rows = [];
    
    if (data.name) {
        // 确定当前节点对应的列名
        let columnKey;
        if (data.superDepartment) columnKey = "SBU";
        else if (data.department) columnKey = "Super Department";
        else if (data.category) columnKey = "Department";
        else if (data.subcategory) columnKey = "Category";
        else columnKey = "Subcategory";
        
        // 复制上下文并填充当前节点数据
        const newRow = {...currentRow};
        newRow[columnKey] = data.name;
        
        // 处理竞品信息
        if (data.keyCompetitor) newRow["Key Competitor"] = data.keyCompetitor.join(", ");
        if (data.otherCompetitor) newRow["Other Competitor"] = data.otherCompetitor.join(", ");
        
        rows.push(newRow);
        
        // 递归处理子数组(排除竞品数组)
        for (const key in data) {
            if (Array.isArray(data[key]) && !["keyCompetitor", "otherCompetitor"].includes(key)) {
                rows = rows.concat(data[key].map(item => generateRows(item, newRow)).flat());
            }
        }
    }
    
    return rows;
}

步骤2:将行数据转换为CSV字符串

按表头顺序拼接行数据,处理含逗号的值(用双引号包裹)避免格式错误。

// 将行数据转换为CSV字符串
function rowsToCsv(headers, rows) {
    const csvRows = [headers.join(",")];
    
    for (const row of rows) {
        const csvRow = headers.map(header => {
            const value = row[header] || "";
            return typeof value === "string" && value.includes(",") ? `"${value}"` : value;
        });
        csvRows.push(csvRow.join(","));
    }
    
    return csvRows.join("\n");
}

步骤3:生成可下载的CSV文件

通过Blob对象创建下载链接,触发浏览器下载。

// 下载CSV文件
function downloadCsv(csvContent, filename = "data.csv") {
    const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
    const url = URL.createObjectURL(blob);
    const link = document.createElement("a");
    link.href = url;
    link.setAttribute("download", filename);
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
}

完整调用示例

// 你的嵌套数组数据
const downloadData = [{
    id: 123,
    name: "ABC",
    superDepartment: [{
        id: 456,
        name: "PQR",
        keyCompetitor: ["JKL"],
        department: [{
            id: 765,
            name: "XYZ",
            category: [{
                id: 965,
                name: "GHJ",
                keyCompetitor: ["NMK"],
                otherCompetitor: ["SDF", "LKJ"],
                subcategory: [
                    {id: 346, name: "DRJ"},
                    {id: 789, name: "SRE"}        
                ]
            }]
        }]
    }]
}];

// 生成并下载CSV
const allRows = downloadData.map(item => generateRows(item)).flat();
const csvContent = rowsToCsv(headers, allRows);
downloadCsv(csvContent);

方案优势

  • 适配任意嵌套层级:递归自动处理所有子节点,无需手动编写多层循环。
  • 列值自动对齐:上下文传递确保子节点行继承父节点的空值或已有数据,符合预期格式。
  • 格式安全高效:统一处理CSV转义,避免格式错误;批量拼接字符串比频繁操作数组更高效。

内容的提问来源于stack exchange,提问作者vjeta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 15:20:01